package jehc.djshi.workflow.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import jehc.djshi.common.base.BaseResult;
import jehc.djshi.common.base.BaseService;
import jehc.djshi.common.util.ExceptionUtil;
import jehc.djshi.common.util.StringUtil;
import jehc.djshi.workflow.dao.*;
import jehc.djshi.workflow.model.*;
import jehc.djshi.workflow.param.*;
import jehc.djshi.workflow.service.*;
import jehc.djshi.workflow.util.ActivitiUtil;
import jehc.djshi.workflow.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.activiti.bpmn.model.UserTask;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.history.HistoricVariableInstance;
import org.activiti.engine.impl.bpmn.behavior.MultiInstanceActivityBehavior;
import org.activiti.engine.impl.bpmn.behavior.ParallelMultiInstanceBehavior;
import org.activiti.engine.impl.bpmn.behavior.SequentialMultiInstanceBehavior;
import org.activiti.engine.impl.bpmn.behavior.UserTaskActivityBehavior;
import org.activiti.engine.impl.persistence.entity.TaskEntity;
import org.activiti.engine.impl.pvm.process.ActivityImpl;
import org.activiti.engine.impl.task.TaskDefinition;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import javax.annotation.Resource;
import java.util.*;
/**
 * @Desc 任务业务处理服务实现
 * @Author 邓纯杰
 * @CreateTime 2012-12-12 12:12:12
 */
@Service
@Slf4j
public class LcTaskServiceImpl extends BaseService implements LcTaskService {

    @Resource
    private LcApplyService lcApplyService;

    @Resource
    ActivitiUtil activitiUtil;

    @Resource
    LcProcessService lcProcessService;

    @Resource
    LcDeploymentHisService lcDeploymentHisService;

    @Resource
    LcNodeAttributeService lcNodeAttributeService;

    @Resource
    LcHisMutilService lcHisMutilService;

    @Resource
    LcSignService lcSignService;

    @Resource
    LcSignRecordService lcSignRecordService;

    @Resource
    LcApprovalService lcApprovalService;

    @Resource
    ActHiTaskinstService actHiTaskinstService;

    @Resource
    ActRuExecutionDao actRuExecutionDao;

    @Resource
    ActRuTaskDao actRuTaskDao;

    @Resource
    ActHiIdentitylinkDao actHiIdentitylinkDao;

    @Resource
    ActRuIdentitylinkDao actRuIdentitylinkDao;

    @Resource
    ActRunVariableDao actRunVariableDao;

    @Resource
    ActHiTaskinstDao actHiTaskinstDao;

    /**
     * 发起流程实例并设置第一个节点发起人并完成第一个节点
     * @param lcHisParam
     * @return
     */
    public BaseResult<ActivityProcessStatusEntity> start(LcHisParam lcHisParam){
        try {
            LcDeploymentHis lcDeploymentHis = lcDeploymentHisService.getLcDeploymentHisById(lcHisParam.getHid_());
            if(null == lcDeploymentHis){
                throw new ExceptionUtil("未能获取到流程部署最新对象,jehc.lcmodules.lcmodel.LcDeploymentHis");
            }
            ProcessDefinition processDefinition = activitiUtil.getProcessDefinition(lcDeploymentHis.getDeploymentId());
            ProcessInstance processInstance = activitiUtil.startProcessInstanceByKey(processDefinition.getKey(), lcHisParam.getBusinessKey(), lcHisParam.getVariables());
            /**Activiti发起实例模块(即提交发起申请)开始**/
            /**调用审批工作流**/
            if(null != processInstance){
                LcApply lcApply = new LcApply();
                if(StringUtil.isEmpty(lcApply.getLcApplyId())){
                    lcApply.setLcApplyId(toUUID());
                }
                lcApply.setCreateTime(getDate());
                lcApply.setProcDefId(processDefinition.getId());
                lcApply.setProcInstId(processInstance.getId());
                lcApply.setTitle(lcHisParam.getTitle());
                lcApply.setBusinessKey(processInstance.getBusinessKey());
                lcApplyService.addLcApply(lcApply);
                ///////////根据当前实例编号查找第一个节点并设置发起人//////////////
                List<Task> tasks = activitiUtil.getTaskService().createTaskQuery().processInstanceId(processInstance.getId()).orderByTaskCreateTime().asc().list();
                if(null != tasks &&!tasks.isEmpty()){
                    Task task = tasks.get(0);
                    //设置当前任务为处理人即发起人
                    activitiUtil.setAssignee(task.getId(),lcHisParam.getMutilValue());

                    if(ActivitiUtil.ACT_CODE_10.equals(lcHisParam.getComplated())){//需要完成第一个任务
                        doStartCompleteTask(task,lcHisParam);
                    }
                }
                log.debug("调用工作流审批信息模块成功");
                return new BaseResult(checkStatus(processInstance.getProcessInstanceId()));
            }else{
                log.debug("调用工作流审批信息模块失败");
                return new BaseResult("-1",false);
            }
            /**Activiti发起实例模块(即提交发起申请)结束**/
        } catch (Exception e) {
            log.error("添加审批异常：{}",e);
            throw new ExceptionUtil(e.getMessage(),e.getCause());
        }
    }

    /**
     * 统一审批
     * @param lcReceiveNParam
     * @return
     */
    public BaseResult approve(LcReceiveNParam lcReceiveNParam){
        String behavior = lcReceiveNParam.getBehavior();
        if(StringUtil.isEmpty(behavior)){
            throw new ExceptionUtil("审批节点行为码为空");
        }
        BaseResult baseResult;
        switch (behavior){
            case ActivitiUtil.BEHAVIOR_0://提交
                baseResult = submit(lcReceiveNParam);
                break;
            case ActivitiUtil.BEHAVIOR_10://同意
                baseResult = agreement(lcReceiveNParam);
                break;
            case ActivitiUtil.BEHAVIOR_20://驳回
                baseResult = reject(lcReceiveNParam);
                break;
            case ActivitiUtil.BEHAVIOR_30://弃权
                baseResult = waiver(lcReceiveNParam);
                break;
            case ActivitiUtil.BEHAVIOR_40://撤回
                baseResult = callBack(lcReceiveNParam);
                break;
            case ActivitiUtil.BEHAVIOR_50://强行终止（终止流程）
                baseResult = termination(lcReceiveNParam);
                break;
            case ActivitiUtil.BEHAVIOR_60://执行跳转
                baseResult = executeJump(lcReceiveNParam);
                break;
            case ActivitiUtil.BEHAVIOR_70://转办
                baseResult = transfer(lcReceiveNParam);
                break;
            case ActivitiUtil.BEHAVIOR_80://委派
                baseResult = delegateTask(lcReceiveNParam);
                break;
            case ActivitiUtil.BEHAVIOR_90://加签
                baseResult = sign(lcReceiveNParam);
                break;
            case ActivitiUtil.BEHAVIOR_100://催办
                baseResult = urge(lcReceiveNParam);
                break;
            case ActivitiUtil.BEHAVIOR_110://设置任务归属人
                baseResult = setOwner(lcReceiveNParam);
                break;
            case ActivitiUtil.BEHAVIOR_120://挂起
                baseResult = suspendProcess(lcReceiveNParam);
                break;
            case ActivitiUtil.BEHAVIOR_130://激活
                baseResult = activateProcess(lcReceiveNParam);
                break;
            default:
                throw new ExceptionUtil("审批节点行为码不合法");
        }
        return baseResult;
    }

    /**
     * 发起流程实例并设置第一个节点发起人并完成第一个节点
     * @param lcReceiveNParam
     * @return
     */
    public BaseResult submit(LcReceiveNParam lcReceiveNParam){
        return completeTask(lcReceiveNParam);
    }

    /**
     * 完成任务（发起人提交任务使用）
     * @param lcReceiveNParam
     * @return
     */
    public BaseResult completeTask(LcReceiveNParam lcReceiveNParam){
        if(StringUtil.isEmpty(lcReceiveNParam.getBehavior())){
            lcReceiveNParam.setBehavior(activitiUtil.BEHAVIOR_0);//默认提交
        }
        boolean res = true;
        if(StringUtil.isEmpty(lcReceiveNParam.getTaskId())){
            new ExceptionUtil("未能获取到任务id");
        }
        HistoricTaskInstance historicTaskInstance = null;
        LcNodeAttribute lcNodeAttribute =null;
        Map<String,Object> map = new HashMap<>();
        List<LcReceiveParam> lcReceiveParamList = lcReceiveNParam.getLcReceiveParams();

        String deploymentId = activitiUtil.getDeploymentIdByTaskId(lcReceiveNParam.getTaskId());//根据当前任务id查找部署编号
        historicTaskInstance = activitiUtil.getTaskById(lcReceiveNParam.getTaskId());//根据当前任务id查找流程实例

        lcNodeAttribute = getNodeAttribute(deploymentId,historicTaskInstance.getTaskDefinitionKey());//当前节点扩展属性
        Boolean needCompleteTask =  false;
        String targetActivityId = null;
        if(null != lcNodeAttribute){
            if("".equals(lcNodeAttribute.getSupportFreeJump()) || ActivitiUtil.ACT_CODE_20.equals(lcNodeAttribute.getSupportFreeJump())){
                needCompleteTask = true;
            }
            List<LcNodeBtn> lcNodeBtns = lcNodeAttribute.getLcNodeBtns();
            if(CollectionUtil.isEmpty(lcNodeBtns)){//如果自定义没有配置下一步节点执行则采用设计器线条
                List<TaskDefinition> taskDefinitions = activitiUtil.getNextTaskDefinitionList(lcReceiveNParam.getTaskId(),null);
                if(!CollectionUtil.isEmpty(taskDefinitions)){
                    targetActivityId = taskDefinitions.get(0).getKey();//取第一个 节点 如果存在多个根据业务需要 判断是否需要只有获取（注意根据业务上要求来）
                }
            }else{
                for(LcNodeBtn lcNodeBtn : lcNodeBtns){
                    if(lcNodeBtn.getLcBtn().getBehavior().equals(lcReceiveNParam.getBehavior())){
                        List<LcJumpRules> lcJumpRules = lcNodeBtn.getLcJumpRules();
                        if(!CollectionUtil.isEmpty(lcJumpRules)){//取一个即可
                            targetActivityId = lcJumpRules.get(0).getTargetNodeId();
                        }
                    }
                }
            }
        }else{
            List<TaskDefinition> taskDefinitions = activitiUtil.getNextTaskDefinitionList(lcReceiveNParam.getTaskId(),null);
            if(!CollectionUtil.isEmpty(taskDefinitions)){
                targetActivityId = taskDefinitions.get(0).getKey();//取第一个 节点 如果存在多个根据业务需要 判断是否需要只有获取（注意根据业务上要求来）
            }
        }
        if(StringUtil.isEmpty(targetActivityId)){
            throw new ExceptionUtil("未能获取到目标节点");
        }

        if(!CollectionUtil.isEmpty(lcReceiveParamList)){
            for(LcReceiveParam lcReceiveParam :lcReceiveParamList){
                if(!StringUtil.isEmpty(deploymentId) && null != historicTaskInstance){
                    LcDeploymentHis lcDeploymentHis = lcDeploymentHisService.getLcDeploymentHisByDeploymentId(deploymentId);
                    if(null != lcDeploymentHis){

                        //获取目标节点
                        LcReceiveParam param = new LcReceiveParam();
                        param.setProcessInstanceId(historicTaskInstance.getProcessInstanceId());
                        if(!StringUtil.isEmpty(lcReceiveParam.getActivityId())){
                            param.setActivityId(lcReceiveParam.getActivityId());
                        }else{
                            param.setActivityId(targetActivityId);
                            lcReceiveParam.setActivityId(targetActivityId);//设定目标节点
                        }
                        boolean mutil = activitiUtil.validateNodeIsMultiInstance(param);

                        //如果会签节点并且会签集合不存在则抛异常
                        if(StringUtil.isEmpty(lcReceiveParam.getMutilValue()) && mutil){
                            throw new ExceptionUtil("目标节点为会签节点，必须指定办理人");
                        }

                        ActivityImpl activityImpl = activitiUtil.getActivityImpl(param);//查找出目标节点

                        //节点的扩展属性（用于做逻辑使用）
                        NodeAttributeParam nodeAttributeParam = new NodeAttributeParam();
                        nodeAttributeParam.setHid_(lcDeploymentHis.getId());
                        nodeAttributeParam.setNodeId(lcReceiveParam.getActivityId());
                        LcNodeAttribute lcNodeAttributeTarget = lcNodeAttributeService.getLcNodeAttribute(nodeAttributeParam);
                        if(null != lcNodeAttributeTarget){
                            String mutilKey = lcNodeAttributeTarget.getMutilKey();
                            if(!StringUtil.isEmpty(mutilKey) && mutil){//如果会签采用扩展表达式则优先使用扩展属性中变量名
                                List<String> list = Arrays.asList(lcReceiveParam.getMutilValue().split(","));
                                map.put(mutilKey, list);//传递变量值
                                try {
                                    addBatchLcHisMutil(list,historicTaskInstance.getProcessInstanceId(),activityImpl);//创建会签节点人员
                                }catch (Exception e){
                                    log.error("创建会签节点人员失败：{}",e);
                                    throw new ExceptionUtil("创建会签节点人员失败,{}",e);
                                }
                                TaskDefinition taskDefinition = null;
                                if(((ActivityImpl) activityImpl).getActivityBehavior() instanceof SequentialMultiInstanceBehavior){//会签多实例串行
                                    SequentialMultiInstanceBehavior sequentialMultiInstanceBehavior = ((SequentialMultiInstanceBehavior) ((ActivityImpl) activityImpl).getActivityBehavior());
                                    taskDefinition = ((UserTaskActivityBehavior)sequentialMultiInstanceBehavior.getInnerActivityBehavior()).getTaskDefinition();
                                }else if(((ActivityImpl) activityImpl).getActivityBehavior() instanceof ParallelMultiInstanceBehavior){//会签多实例并行
                                    ParallelMultiInstanceBehavior parallelMultiInstanceBehavior =  ((ParallelMultiInstanceBehavior) ((ActivityImpl) activityImpl).getActivityBehavior());
                                    taskDefinition = ((UserTaskActivityBehavior)parallelMultiInstanceBehavior.getInnerActivityBehavior()).getTaskDefinition();
                                }else if(((ActivityImpl) activityImpl).getActivityBehavior() instanceof MultiInstanceActivityBehavior){
                                    MultiInstanceActivityBehavior multiInstanceActivityBehavior =  ((MultiInstanceActivityBehavior) ((ActivityImpl) activityImpl).getActivityBehavior());
                                    taskDefinition = ((UserTaskActivityBehavior)multiInstanceActivityBehavior.getInnerActivityBehavior()).getTaskDefinition();
                                }
                                if(null != taskDefinition && null == taskDefinition.getAssigneeExpression()){//如果会签节点中没有办理人变量没有设置 则标记为需要重新动态分配
                                    lcReceiveParam.setNeedHandledTransactor(true);
                                }
                            }else{
                                if ("userTask".equals(activityImpl.getProperty("type")) && ((ActivityImpl) activityImpl).getActivityBehavior() instanceof UserTaskActivityBehavior){
                                    TaskDefinition taskDefinition = ((UserTaskActivityBehavior) ((ActivityImpl) activityImpl).getActivityBehavior()).getTaskDefinition();
                                    if(null != taskDefinition.getAssigneeExpression()){//如果审批人中有变量 则无需标记处理人
                                        String expression  = taskDefinition.getAssigneeExpression().getExpressionText().replace("${","").replace("}","");
                                        map.put(expression, lcReceiveParam.getMutilValue());//传递变量值
                                    }else{
                                        //普通节点
                                        lcReceiveParam.setNeedHandledTransactor(true);
                                    }
                                }else{
                                    //普通节点
                                    lcReceiveParam.setNeedHandledTransactor(true);
                                }
                            }
                        }else{
                            if ("userTask".equals(activityImpl.getProperty("type")) && ((ActivityImpl) activityImpl).getActivityBehavior() instanceof UserTaskActivityBehavior){
                                TaskDefinition taskDefinition = ((UserTaskActivityBehavior) ((ActivityImpl) activityImpl).getActivityBehavior()).getTaskDefinition();
                                if(null != taskDefinition.getAssigneeExpression() && !StringUtil.isEmpty(taskDefinition.getAssigneeExpression().getExpressionText())){//如果审批人中有变量 则无需标记处理人
                                    String expression  = taskDefinition.getAssigneeExpression().getExpressionText().replace("${","").replace("}","");
                                    map.put(expression, lcReceiveParam.getMutilValue());//传递变量值
                                }else{
                                    //普通节点
                                    lcReceiveParam.setNeedHandledTransactor(true);
                                }
                            }else{
                                //普通节点
                                lcReceiveParam.setNeedHandledTransactor(true);
                            }
                        }
                    }
                }
            }
        }
        persistenceAppro(historicTaskInstance,lcReceiveNParam);//持久化日志
        if(needCompleteTask){
            activitiUtil.completeTask(lcReceiveNParam.getTaskId(),map);//需要根据逻辑编写，如果map变量中指定了审批人则可以无需 进行后续处理，业务线可以根据实际情况处理
        }else{
            lcReceiveNParam.setVariables(map);//设置变量
            lcReceiveNParam.setActivityId(targetActivityId);
            activitiUtil.jump(lcReceiveNParam);//注意此时跳转后 不需要终止 还是要继续执行下面命令为了重新分配人等等
        }
        if( null != historicTaskInstance){
            List<Task> tasks = activitiUtil.findTaskListByInstanceId(historicTaskInstance.getProcessInstanceId());
            if(!CollectionUtil.isEmpty(tasks)){
                for(Task task: tasks){
                    String nodeId = task.getTaskDefinitionKey();//节点编号
                    //重新指定人
                    if(!CollectionUtil.isEmpty(lcReceiveParamList)){
                        for(LcReceiveParam lcReceiveParam :lcReceiveParamList){
                            if(lcReceiveParam.getNeedHandledTransactor() && nodeId.equals(lcReceiveParam.getActivityId())){//判断是否需要重新设置值
                                if(!StringUtil.isEmpty(lcReceiveParam.getMutilValue())){//处理办理人单个
                                    String mutilValue = doLcReceiveParam(lcReceiveParam);
                                    if(!StringUtil.isEmpty(mutilValue)){
                                        activitiUtil.setAssignee(task.getId(),mutilValue);
                                    }
                                }
                                if(!StringUtil.isEmpty(lcReceiveParam.getCandidates())){//处理候选人

                                }
                                if(StringUtil.isEmpty(lcReceiveParam.getCandidateGroup())){//处理组

                                }
                                continue;
                            }
                        }
                    }
                }
            }
        }

        //返回流程实例是否结束
        String currentActivityId = historicTaskInstance.getTaskDefinitionKey();//当前节点id
        String currentName = historicTaskInstance.getName();//当前审批任务节点名称
        ActivityProcessStatusEntity activityProcessStatusEntity = checkStatus(historicTaskInstance.getProcessInstanceId());
        activityProcessStatusEntity.setCurrentActivityId(currentActivityId);
        activityProcessStatusEntity.setCurrentName(currentName);
        if(!CollectionUtil.isEmpty(lcReceiveNParam.getLcReceiveParams())){//处理人员
            activityProcessStatusEntity.setAccount(lcReceiveNParam.getLcReceiveParams().get(0).getMutilValue());
        }
        BaseResult baseResult = new BaseResult();
        baseResult.setData(activityProcessStatusEntity);
        baseResult.setSuccess(res);
        return baseResult;
    }

    /**
     * 同意
     * @param lcReceiveNParam
     * @return
     */
    public BaseResult agreement(LcReceiveNParam lcReceiveNParam){
        if(StringUtil.isEmpty(lcReceiveNParam.getBehavior())){
            lcReceiveNParam.setBehavior(activitiUtil.BEHAVIOR_10);//同意
        }
        boolean res = true;
        if(StringUtil.isEmpty(lcReceiveNParam.getTaskId())){
            new ExceptionUtil("未能获取到任务id");
        }
        HistoricTaskInstance historicTaskInstance = null;
        LcNodeAttribute lcNodeAttribute =null;
        Map<String,Object> map = lcReceiveNParam.getVariables();
        if(CollectionUtil.isEmpty(map)){
            map = new HashMap<>();
        }
        List<LcReceiveParam> lcReceiveParamList = lcReceiveNParam.getLcReceiveParams();

        String deploymentId = activitiUtil.getDeploymentIdByTaskId(lcReceiveNParam.getTaskId());//根据当前任务id查找部署编号
        historicTaskInstance = activitiUtil.getTaskById(lcReceiveNParam.getTaskId());//根据当前任务id查找流程实例
        String currentActivityId = historicTaskInstance.getTaskDefinitionKey();//当前节点id
        String currentName = historicTaskInstance.getName();//当前审批任务节点名称
        lcNodeAttribute = getNodeAttribute(deploymentId,historicTaskInstance.getTaskDefinitionKey());//当前节点扩展属性

        String targetActivityId = "";//目标节点id
        List<String> list = new ArrayList<>();
        ActivityImpl activityImpl = null;
        boolean canBatchLcHisMutil = false;

        if(CollectionUtil.isEmpty(lcReceiveParamList)){
            lcReceiveParamList = new ArrayList<>();
            LcReceiveParam lcReceiveParam = new LcReceiveParam();
            lcReceiveParamList.add(lcReceiveParam);
            lcReceiveNParam.setLcReceiveParams(lcReceiveParamList);
        }

        if(!CollectionUtil.isEmpty(lcReceiveParamList)){
            for(LcReceiveParam lcReceiveParam :lcReceiveParamList){
                if(!StringUtil.isEmpty(deploymentId) && null != historicTaskInstance){
                    LcDeploymentHis lcDeploymentHis = lcDeploymentHisService.getLcDeploymentHisByDeploymentId(deploymentId);
                    if(null != lcDeploymentHis){

                        targetActivityId = lcReceiveParam.getActivityId();

                        //目标节点获取方式开始
                        if(StringUtil.isEmpty(targetActivityId)){
                            targetActivityId = setLcReceiveNParam(lcNodeAttribute,lcReceiveNParam);
                        }
                        lcReceiveParam.setActivityId(targetActivityId);
                        //目标节点获取方式结束

                        //获取目标节点属性
                        LcReceiveParam param = new LcReceiveParam();
                        param.setProcessInstanceId(historicTaskInstance.getProcessInstanceId());
                        param.setActivityId(lcReceiveParam.getActivityId());
                        boolean mutil = activitiUtil.validateNodeIsMultiInstance(param);

                        //如果会签节点并且会签集合不存在则抛异常
                        if(StringUtil.isEmpty(lcReceiveParam.getMutilValue()) && mutil){
                            throw new ExceptionUtil("目标节点为会签节点，必须指定办理人");
                        }

                        activityImpl = activitiUtil.getActivityImpl(param);//查找出目标节点

                        //节点的扩展属性（用于做逻辑使用）
                        NodeAttributeParam nodeAttributeParam = new NodeAttributeParam();
                        nodeAttributeParam.setHid_(lcDeploymentHis.getId());
                        nodeAttributeParam.setNodeId(lcReceiveParam.getActivityId());
                        LcNodeAttribute lcNodeAttributeTarget = lcNodeAttributeService.getLcNodeAttribute(nodeAttributeParam);
                        if(null != lcNodeAttributeTarget){
                            String mutilKey = lcNodeAttributeTarget.getMutilKey();
                            if(!StringUtil.isEmpty(mutilKey) && mutil){//如果会签采用扩展表达式则优先使用扩展属性中变量名
                                list = Arrays.asList(lcReceiveParam.getMutilValue().split(","));
                                map.put(mutilKey, list);//传递变量值
                                /* 废弃该地方存储下个节点会签人（更新代码至validateCanBatchLcHisMutil(list, historicTaskInstance,activityImpl);）
                                try {
                                    addBatchLcHisMutil(list,historicTaskInstance.getProcessInstanceId(),activityImpl);//创建会签节点人员
                                }catch (Exception e){
                                    log.error("创建会签节点人员失败：{}",e);
                                    throw new ExceptionUtil("创建会签节点人员失败,{}",e);
                                }*/
                                canBatchLcHisMutil = true;
                                TaskDefinition taskDefinition = null;
                                if(((ActivityImpl) activityImpl).getActivityBehavior() instanceof SequentialMultiInstanceBehavior){//会签多实例串行
                                    SequentialMultiInstanceBehavior sequentialMultiInstanceBehavior = ((SequentialMultiInstanceBehavior) ((ActivityImpl) activityImpl).getActivityBehavior());
                                    taskDefinition = ((UserTaskActivityBehavior)sequentialMultiInstanceBehavior.getInnerActivityBehavior()).getTaskDefinition();
                                }else if(((ActivityImpl) activityImpl).getActivityBehavior() instanceof ParallelMultiInstanceBehavior){//会签多实例并行
                                    ParallelMultiInstanceBehavior parallelMultiInstanceBehavior =  ((ParallelMultiInstanceBehavior) ((ActivityImpl) activityImpl).getActivityBehavior());
                                    taskDefinition = ((UserTaskActivityBehavior)parallelMultiInstanceBehavior.getInnerActivityBehavior()).getTaskDefinition();
                                }else if(((ActivityImpl) activityImpl).getActivityBehavior() instanceof MultiInstanceActivityBehavior){
                                    MultiInstanceActivityBehavior multiInstanceActivityBehavior =  ((MultiInstanceActivityBehavior) ((ActivityImpl) activityImpl).getActivityBehavior());
                                    taskDefinition = ((UserTaskActivityBehavior)multiInstanceActivityBehavior.getInnerActivityBehavior()).getTaskDefinition();
                                }
                                if(null != taskDefinition && null == taskDefinition.getAssigneeExpression()){//如果会签节点中没有办理人变量没有设置 则标记为需要重新动态分配
                                    lcReceiveParam.setNeedHandledTransactor(true);
                                }
                            }else{
                                if ("userTask".equals(activityImpl.getProperty("type")) && ((ActivityImpl) activityImpl).getActivityBehavior() instanceof UserTaskActivityBehavior){
                                    TaskDefinition taskDefinition = ((UserTaskActivityBehavior) ((ActivityImpl) activityImpl).getActivityBehavior()).getTaskDefinition();
                                    if(null != taskDefinition.getAssigneeExpression()){//如果审批人中有变量 则无需标记处理人
                                        String expression  = taskDefinition.getAssigneeExpression().getExpressionText().replace("${","").replace("}","");
                                        map.put(expression, lcReceiveParam.getMutilValue());//传递变量值
                                    }else{
                                        //普通节点
                                        lcReceiveParam.setNeedHandledTransactor(true);
                                    }
                                }else{
                                    //普通节点
                                    lcReceiveParam.setNeedHandledTransactor(true);
                                }
                            }
                        }else{
                            if ("userTask".equals(activityImpl.getProperty("type")) && ((ActivityImpl) activityImpl).getActivityBehavior() instanceof UserTaskActivityBehavior){
                                TaskDefinition taskDefinition = ((UserTaskActivityBehavior) ((ActivityImpl) activityImpl).getActivityBehavior()).getTaskDefinition();
                                if(null != taskDefinition.getAssigneeExpression() && !StringUtil.isEmpty(taskDefinition.getAssigneeExpression().getExpressionText())){//如果审批人中有变量 则无需标记处理人
                                    String expression  = taskDefinition.getAssigneeExpression().getExpressionText().replace("${","").replace("}","");
                                    map.put(expression, lcReceiveParam.getMutilValue());//传递变量值
                                }else{
                                    //普通节点
                                    lcReceiveParam.setNeedHandledTransactor(true);
                                }
                            }else{
                                //普通节点
                                lcReceiveParam.setNeedHandledTransactor(true);
                            }
                        }
                    }
                }
            }
        }
        boolean needCompleteTask = true;
        if(ActivitiUtil.ACT_CODE_10.equals(lcReceiveNParam.getComplete()) || StringUtil.isEmpty(lcReceiveNParam.getComplete())){
            needCompleteTask = false;
        }
        if(lcReceiveNParam.getBehavior().equals(ActivitiUtil.BEHAVIOR_10) || lcReceiveNParam.getBehavior().equals(ActivitiUtil.BEHAVIOR_30)){//只处理节点同意或弃权动作时候调用该逻辑（可能出现会签）
            if(lcReceiveNParam.isNeedPersistenceAppro()){
                persistenceAppro(historicTaskInstance,lcReceiveNParam);//持久化日志
            }
            Map<String,Object> multiMap = new HashMap<>();
            if(lcReceiveNParam.isNeedComputeMutil()){
                multiMap = computeMutil(lcReceiveNParam,lcNodeAttribute); //处理会签结果（此时需要增加一个条件，如果投票结果 可能直接满足了 此时会签任务并没有完全结束，比如20个人投票 规则中只需要3个人通过 那么此时 就应该终止其它任务 并跳转到新节点 此时 就不能用completeTask方法 应该用jump方法）
            }else{
                log.info("无需重新计算节点处理结果,原因该动作是通过驳回反向动作过来,{}",lcReceiveNParam);
                needCompleteTask = false;
            }
            if(!CollectionUtil.isEmpty(multiMap)){
                log.info("计算节点处理结果,{}",multiMap);
                if((Boolean) multiMap.get("multilInstance")){ //如果会签节点 并且未满足条件 还需要继续完成任务
                    if(false == (Boolean) multiMap.get("result")){//继续完成任务
                        activitiUtil.completeTask(lcReceiveNParam.getTaskId(),map);//需要根据逻辑编写，如果map变量中指定了审批人则可以无需 进行后续处理，业务线可以根据实际情况处理
                        log.info("会签节点操作通过（同意）逻辑 并未达到结果 则继续执行完成操作，此时直接返回结果");
                        ActivityProcessStatusEntity activityProcessStatusEntity =checkStatus(historicTaskInstance.getProcessInstanceId());
                        activityProcessStatusEntity.setCurrentName(currentName);
                        activityProcessStatusEntity.setCurrentActivityId(currentActivityId);
                        return new BaseResult("会签节点操作同意（通过）逻辑 达到结果 则继续执行完成操作",true,activityProcessStatusEntity);
                    }else{//说明是会签节点 并且有结果了 需要调用跳转命令，注意 下面步骤还是要继续执行的 因为驳回后的目标节点 都要重新跳转，并且节点处理人也需要处理 所以不需要终止
                        if(ActivitiUtil.ACT_CODE_10.equals(lcReceiveNParam.getComplete())){//完成动作向下个节点流转采用模式:10跳转模式 20采用原生引擎完成动作
                            needCompleteTask = false;
                        }
                    }
                }else{//普通节点 也需要将其目标节点找到
                    if(ActivitiUtil.ACT_CODE_10.equals(lcReceiveNParam.getComplete())){//完成动作向下个节点流转采用模式:10跳转模式 20采用原生引擎完成动作
                        setActivityIdByNodeBtn(lcReceiveNParam ,lcNodeAttribute);
                        needCompleteTask = false;
                    }
                }
            }
            if(null != multiMap.get("actionResult") && multiMap.get("actionResult").equals(ActivitiUtil.ACT_CODE_20)){ //说明会签结果为反向结果
                //执行驳回逻辑
                log.info("会签结果按驳回执行");
                lcReceiveNParam.setNeedComputeMutil(false);//反向结果无需重新计算规则
                lcReceiveNParam.setNeedPersistenceAppro(false);//反向结果无需持久化日志
                setActivityId(lcReceiveNParam,lcNodeAttribute,ActivitiUtil.BEHAVIOR_20);//重新设置方向结果对应的目标节点
                lcReceiveNParam.setBehavior(ActivitiUtil.BEHAVIOR_20);
                //找出会签审批人中点击同意动作后选择的最新目标节点处理人
//                getTargetMutilValue(lcReceiveNParam,historicTaskInstance,true,lcReceiveNParam.getActivityId());//构造最后一个审批人点击同意后的下一个节点审批人
                return reject(lcReceiveNParam);
            }else{
                if(canBatchLcHisMutil){
                    validateCanBatchLcHisMutil(list, historicTaskInstance,activityImpl);//验证是否需要完成会签结果并创建下个节点会签人
                }
            }
        }else{
            //如果同意动作中出现驳回行为 则说明操作会签节点 点击驳回操作 与配置规则中不匹配 出现反向结果为同意，所以无需再次处理会签动作
        }
        if(needCompleteTask){
            log.info("同意动作后续采用方式为完成，{},needCompleteTask:{}",lcReceiveNParam.toString(),needCompleteTask);
            activitiUtil.completeTask(lcReceiveNParam.getTaskId(),map);//需要根据逻辑编写，如果map变量中指定了审批人则可以无需 进行后续处理，业务线可以根据实际情况处理
        }else{
            log.info("同意动作后续采用方式为跳转，{},needCompleteTask:{}",lcReceiveNParam.toString(),needCompleteTask);
            lcReceiveNParam.setVariables(map);//设置变量
            lcReceiveNParam.setActivityId(targetActivityId);
            activitiUtil.jump(lcReceiveNParam);//注意此时跳转后 不需要终止 还是要继续执行下面命令为了重新分配人等等
        }
        setAssignee(historicTaskInstance,lcReceiveNParam);//设置处理人
        ActivityProcessStatusEntity activityProcessStatusEntity = checkStatus(historicTaskInstance.getProcessInstanceId());
        activityProcessStatusEntity.setCurrentActivityId(currentActivityId);
        activityProcessStatusEntity.setCurrentName(currentName);
        if(!CollectionUtil.isEmpty(lcReceiveNParam.getLcReceiveParams())){//处理人员
            activityProcessStatusEntity.setAccount(lcReceiveNParam.getLcReceiveParams().get(0).getMutilValue());
        }
        BaseResult baseResult = new BaseResult();
        baseResult.setData(activityProcessStatusEntity);
        baseResult.setSuccess(res);
        return baseResult;
    }

    /**
     * 撤回（运行时实例撤回方式）
     * @param lcReceiveNParam
     * @return
     */
    public BaseResult callBack(LcReceiveNParam lcReceiveNParam){
        lcReceiveNParam.setBehavior(ActivitiUtil.BEHAVIOR_40);
        HistoricTaskInstance historicTaskInstance = activitiUtil.getTaskById(lcReceiveNParam.getTaskId());//从历史中找到自己提交的任务
        if(activitiUtil.validatePEnd(historicTaskInstance.getProcessInstanceId())){
            log.warn("流程实例已结束不能撤回！{}",lcReceiveNParam);
            throw new ExceptionUtil("流程实例已结束不能撤回！");
        }
        LcNodeAttribute lcNodeAttribute = getLcNodeAttributeByTaskId(lcReceiveNParam.getTaskId());//当前节点扩展属性

        if(null != lcNodeAttribute && !StringUtil.isEmpty(lcNodeAttribute.getRecall()) && ActivitiUtil.ACT_CODE_10.equals(lcNodeAttribute.getRecall())){
            log.warn("撤回操作时，该节点配置了不允许主动撤回操作！{}",lcReceiveNParam);
            throw new ExceptionUtil("撤回操作时，该节点配置了不允许主动撤回操作！");
        }

        validateAllowRecall(historicTaskInstance);//验证当前运行的任务节点是否可被撤回

        //不能被撤回到会签节点
        String procDefId = historicTaskInstance.getProcessDefinitionId();
        if(StringUtil.isEmpty(procDefId)){
            log.warn("撤回操作时，未能查到流程定义id！{}",lcReceiveNParam);
            throw new ExceptionUtil("撤回操作时，未能查到流程定义id！");
        }
        ProcessDefinition processDefinition = activitiUtil.getProcessDefinitionByDid(procDefId);
        if(null == processDefinition){
            log.warn("撤回操作时，未能查到流程定义！{}-{}",lcReceiveNParam,processDefinition);
            throw new ExceptionUtil("撤回操作时，未能查到流程定义id！");
        }
        String deploymentId = processDefinition.getDeploymentId();
        if(StringUtil.isEmpty(procDefId)){
            log.warn("撤回操作时，未能查到流程部署id！{}",lcReceiveNParam);
            throw new ExceptionUtil("撤回操作时，未能查到流程部署id！");
        }
        LcDeploymentHis lcDeploymentHis = lcDeploymentHisService.getLcDeploymentHisByDeploymentId(deploymentId);
        if(null == lcDeploymentHis){
            log.warn("撤回操作时，未能查到流程部署对象！{}",lcReceiveNParam);
            throw new ExceptionUtil("撤回操作时，未能查到流程部署对象！");
        }
        String bpmn = lcDeploymentHis.getBpmn();
        UserTask userTask = activitiUtil.getUserTask(bpmn,historicTaskInstance.getTaskDefinitionKey());
        if(null == userTask){
            log.warn("撤回操作时，未能查到UserTask！{}",lcReceiveNParam);
            throw new ExceptionUtil("撤回操作时，未能查到UserTask！");
        }
        boolean mutil = activitiUtil.validateNodeIsMultiInstance(userTask);
        if(mutil){
            //撤回到的节点是会签节点不能撤回
            log.warn("撤回操作时，该节点为会签节点不能撤回！{}",lcReceiveNParam);
            throw new ExceptionUtil("该节点为会签节点不能撤回！");
        }
        //取出历史任务对应的节点（bpm文件中节点编号）
        lcReceiveNParam.setActivityId(historicTaskInstance.getTaskDefinitionKey());//即表示即将要退回到该节点
        //取出当前流程下的活动任务
        List<Task> tasks = activitiUtil.getTaskListByProcessInstanceId(historicTaskInstance.getProcessInstanceId());
        if(!CollectionUtil.isEmpty(tasks)){
            lcReceiveNParam.setTaskId(tasks.get(0).getId());//设置为任务 表示通过这个任务跳转到指定节点
        }

        persistenceAppro(historicTaskInstance,lcReceiveNParam);//持久化日志

        return activitiUtil.jump(lcReceiveNParam);
    }

    /**
     * 驳回
     * @param lcReceiveNParam
     * @return
     */
    public BaseResult reject(LcReceiveNParam lcReceiveNParam){
        if(StringUtil.isEmpty(lcReceiveNParam.getBehavior())){
            lcReceiveNParam.setBehavior(ActivitiUtil.BEHAVIOR_20);
        }
        HistoricTaskInstance historicTaskInstance = null;
        LcNodeAttribute lcNodeAttribute = null;//当前节点属性

        Map<String,Object> mutilValueMap = new HashMap<>();//审批人

        LcNodeAttribute targetLcNodeAttribute = null;//目标节点属性

        boolean multiInstance = false;//目标节点是否为会签节点 默认false

        boolean mutilComplate = false;//会签节点是否有结果导向

        if(StringUtil.isEmpty(lcReceiveNParam.getTaskId())){
            new ExceptionUtil("未能获取到当前任务id");
        }

        //查找节点规则
        //当前节点的扩展属性（用于做逻辑使用）
        String deploymentId = activitiUtil.getDeploymentIdByTaskId(lcReceiveNParam.getTaskId());
        historicTaskInstance = activitiUtil.getTaskById(lcReceiveNParam.getTaskId());
        if(StringUtil.isEmpty(deploymentId)){
            new ExceptionUtil("未能获取到部署编号");
        }
        if(null == historicTaskInstance){
            new ExceptionUtil("流程实例不存在");
        }
        String currentActivityId = historicTaskInstance.getTaskDefinitionKey();
        String currentName = historicTaskInstance.getName();//当前审批任务节点名称
        LcReceiveParam param = new LcReceiveParam();
        param.setTaskId(lcReceiveNParam.getTaskId());
        ActivityImpl activityImpl = activitiUtil.getActivityImpl(param);//查找出当前任务对应的节点
        if(null == activityImpl){
            new ExceptionUtil("未能找到当前节点");
        }
        param.setActivityId(activityImpl.getId());//设置当前节点
        lcNodeAttribute = getNodeAttribute(deploymentId,activityImpl.getId());//当前节点扩展属性

        if(CollectionUtil.isEmpty(lcReceiveNParam.getLcReceiveParams())){
            LcReceiveParam lcReceiveParam = new LcReceiveParam();
            List<LcReceiveParam> lcReceiveParams = new ArrayList<>();
            lcReceiveParams.add(lcReceiveParam);
            lcReceiveNParam.setLcReceiveParams(lcReceiveParams);
        }

        if(lcReceiveNParam.getBehavior().equals(ActivitiUtil.BEHAVIOR_20) ){//只处理节点驳回动作时候调用该逻辑（可能出现会签）
            if(lcReceiveNParam.isNeedPersistenceAppro()){
                persistenceAppro(historicTaskInstance,lcReceiveNParam);//持久化日志
            }
            //需要处理当前节点非会签节点点击驳回
            Map<String,Object> multiMap = new HashMap<>();
            if(lcReceiveNParam.isNeedComputeMutil()){
                multiMap = computeMutil(lcReceiveNParam,lcNodeAttribute); //处理会签结果（需处理会签，如果是会签节点拒绝时，未满足最终的结果条件 此时是不能用跳转模式，原因如果你跳转了 那么节点就没有了 会签的其它任务都没有了）
            }else{
                log.info("无需重新计算节点处理结果,原因该动作是通过同意反向动作过来,{}",lcReceiveNParam);
                mutilComplate = true;
            }
            if(!CollectionUtil.isEmpty(multiMap)){
                if((Boolean) multiMap.get("multilInstance")){
                    if(false==(Boolean) multiMap.get("result")){//继续完成任务
                        activitiUtil.completeTask(lcReceiveNParam.getTaskId(),lcReceiveNParam.getVariables());//需要根据逻辑编写，如果map变量中指定了审批人则可以无需 进行后续处理，业务线可以根据实际情况处理
                        log.info("会签节点操作驳回（拒绝）逻辑 并未达到结果 则继续执行完成操作");
                        ActivityProcessStatusEntity activityProcessStatusEntity =checkStatus(historicTaskInstance.getProcessInstanceId());
                        activityProcessStatusEntity.setCurrentName(currentName);
                        activityProcessStatusEntity.setCurrentActivityId(currentActivityId);
                        //查找当前会签节点审批人
                        activityProcessStatusEntity.setAccount(getMutilValue(historicTaskInstance,true,currentActivityId));
                        return new BaseResult("会签节点操作驳回（拒绝）逻辑 并未达到结果 则继续执行完成操作",true,activityProcessStatusEntity);
                    }else{//说明是会签节点 并且有结果了 需要调用跳转命令，注意 下面步骤还是要继续执行的 因为驳回后的目标节点 都要重新跳转，并且节点处理人也需要处理 所以不需要终止
                        mutilComplate = true;//说明有结果
                    }
                    if(null != multiMap.get("actionResult") && multiMap.get("actionResult").equals(ActivitiUtil.ACT_CODE_10)){ //说明会签结果为反向结果
                        //执行通过逻辑
                        log.info("会签结果按通过执行");
                        lcReceiveNParam.setNeedComputeMutil(false);//反向结果无需重新计算规则
                        lcReceiveNParam.setNeedPersistenceAppro(false);//反向结果为同意则无需再次持久化日志
                        setActivityId(lcReceiveNParam,lcNodeAttribute,ActivitiUtil.BEHAVIOR_10);//重新设置方向结果对应的目标节点
                        lcReceiveNParam.setBehavior(ActivitiUtil.BEHAVIOR_10);
                        //找出会签审批人中点击同意动作后选择的最新目标节点处理人
                        getTargetMutilValue(lcReceiveNParam,historicTaskInstance,true,currentActivityId);//构造最后一个审批人点击同意后的下一个节点审批人
                        return agreement(lcReceiveNParam);
                    }
                }
            }
        }

        if(StringUtil.isEmpty(lcReceiveNParam.getActivityId())){//步骤一.目标节点为空则按上级节点驳回
            if(lcNodeAttribute == null){//如果当前节点没有扩展属性则按默认逻辑走，此时至需要查找上级即可 节点执行人采用按（如果前端没有传递审批人，则调出原节点审批人，反正采用新的审批人）
                //查找上级节点（按最新流向查找）
                ActivityImpl activity = activitiUtil.getLastUserTaskActivityImpl(param);
                if(null != activity){
                    lcReceiveNParam.setActivityId(activity.getId());//需要将上级节点编号找到并放入进去 默认按最近一次流向为上级节点（即目标节点）
                }else{//如果找不到最新流向 则通过设计器中连线查找出对应的目标
                    List<UserTask> userTasks = activitiUtil.previousNode(lcReceiveNParam);
                    if(CollectionUtil.isEmpty(userTasks)){
                        throw new ExceptionUtil("当前节点的未配置目标节点并且流程设计器中也没有上级节点！");
                    }
                    if(userTasks.size()>1){
                        throw new ExceptionUtil("当前节点的未配置目标节点并且流程设计器中存在多个上级节点！");
                    }
                    lcReceiveNParam.setActivityId(userTasks.get(0).getId());
                }
            }
        }

        //判断当前节点的扩展属性驳回方式
        if(null != lcNodeAttribute){
            String rejectExecutor = StringUtil.isEmpty(lcNodeAttribute.getRejectExecutor())?ActivitiUtil.BEHAVIOR_10:lcNodeAttribute.getRejectExecutor();//驳回后执行人：10采用原节点审批人执行20重新指定人30采用原节点配置规则选举人 默认10
            String rejectType = StringUtil.isEmpty(lcNodeAttribute.getRejectType())?ActivitiUtil.ACT_CODE_30:lcNodeAttribute.getRejectType();//驳回方式:10按最近一次流入节点 20驳回至发起人 30按自定义节点驳回 40按流程图驳回至上级 默认30
            if(ActivitiUtil.ACT_CODE_20.equals(lcNodeAttribute.getRejectTerminationOtherExecution())){
                lcReceiveNParam.setEndAllActivityInstances(true);//驳该节点点击驳回时是否终止其它运行实例10否20是
            }
            String rejectRule =  StringUtil.isEmpty(lcNodeAttribute.getRejectRule())?ActivitiUtil.ACT_CODE_10:lcNodeAttribute.getRejectRule();//按流程图上级驳回规则:10如果当前节点在流程图上存在多个任务随机一个 20如果当前节点在流程图上存在多个任务抛出异常
            /////////////////1.驳回方式///////////////
            if(!StringUtil.isEmpty(rejectType)){
                if(rejectType.equals(ActivitiUtil.ACT_CODE_10)){//按按最近一次流入节点作为上级节点进行驳回
                    //查找上级节点
                    ActivityImpl activity = activitiUtil.getLastUserTaskActivityImpl(param);
                    if(null != activity){

                        lcReceiveNParam.setActivityId(activity.getId());//需要将上级节点编号找到并放入进去 默认按最近一次流向为上级节点（即目标节点）

                        //验证目标节点是否会签节点
                        LcReceiveParam par = new LcReceiveParam();
                        par.setActivityId(activity.getId());
                        par.setProcessInstanceId(historicTaskInstance.getProcessInstanceId());
                        multiInstance = activitiUtil.validateNodeIsMultiInstance(par);
                    }else{
                        throw new ExceptionUtil("当前节点配置了驳回方式按按最近一次流入节点走向，但是未能找到上级节点！");
                    }
                }
                if(rejectType.equals(ActivitiUtil.ACT_CODE_20)){//驳回至发起人
                    //查询出发起人节点
                    LcNodeAttribute attribute = getLcNodeAttributeInitiator(lcNodeAttribute.getHid_());
                    if(null == attribute){
                        throw new ExceptionUtil("当前节点配置了驳回发起人，但是未能找到发起人节点！");//找不到则抛异常
                    }
                    lcReceiveNParam.setActivityId(attribute.getNodeId());//需要将发起人找到并放入进去
                }
                if(rejectType.equals(ActivitiUtil.ACT_CODE_30)){//按自定义节点驳回
                    setActivityIdByNodeBtn(lcReceiveNParam ,lcNodeAttribute);//查找自定义节点

                    if(StringUtil.isEmpty(lcReceiveNParam.getActivityId())){
                        setLcReceiveNParam(lcNodeAttribute,lcReceiveNParam);//重新设置
                        if(StringUtil.isEmpty(lcReceiveNParam.getActivityId())){
                            throw new ExceptionUtil("该任务节点驳回时候设定了驳回方式为自定义节点驳回，但是自定义的目标节点为空");
                        }
                    }

                    //验证目标节点是否会签节点
                    LcReceiveParam par = new LcReceiveParam();
                    par.setActivityId(lcReceiveNParam.getActivityId());
                    par.setProcessInstanceId(historicTaskInstance.getProcessInstanceId());
                    multiInstance = activitiUtil.validateNodeIsMultiInstance(par);
                }
                if(rejectType.equals(ActivitiUtil.ACT_CODE_40)){//按流程图走向驳回
                    //查找上级节点
                    List<UserTask> previousList = activitiUtil.previousNode(lcReceiveNParam);
                    if(CollectionUtil.isEmpty(previousList)){
                        throw new ExceptionUtil("当前节点配置了驳回方式按流程图走向，但是未能找到上级节点！");
                    }
                    if(previousList.size()==1){
                        UserTask userTask = previousList.get(0);
                        lcReceiveNParam.setActivityId(userTask.getId());//需要将上级节点编号找到并放入进去

                        //验证目标节点是否会签节点
                        LcReceiveParam par = new LcReceiveParam();
                        par.setActivityId(lcReceiveNParam.getActivityId());
                        par.setProcessInstanceId(historicTaskInstance.getProcessInstanceId());
                        multiInstance = activitiUtil.validateNodeIsMultiInstance(par);

                    }else{
                        if(rejectRule.equals(ActivitiUtil.ACT_CODE_20)){//如果查询出多个 并且属性配置为抛异常
                            throw new ExceptionUtil("当前节点配置了驳回方式按流程图走向，并且规则为当查询多个节点则抛异常！");
                        }else{//否则随机选举一个节点
                            lcReceiveNParam.setActivityId(previousList.get(0).getId());//需要将上级节点编号找到并放入进去

                            //验证目标节点是否会签节点
                            LcReceiveParam par = new LcReceiveParam();
                            par.setActivityId(lcReceiveNParam.getActivityId());
                            par.setProcessInstanceId(historicTaskInstance.getProcessInstanceId());
                            multiInstance = activitiUtil.validateNodeIsMultiInstance(par);
                        }
                    }
                }
                ///////////2.驳回后执行规则///////////
                if(!StringUtil.isEmpty(rejectExecutor)){
                    if(rejectExecutor.equals(ActivitiUtil.ACT_CODE_10)){//采用原节点审批人执行
                        //调出原节点审批人
                        mutilValueMap = getOldMutilValue(lcReceiveNParam,historicTaskInstance,multiInstance);
                    }
                    if(rejectExecutor.equals(ActivitiUtil.ACT_CODE_20)){//重新指定人
                        if(StringUtil.isEmpty(lcReceiveNParam.getMutilValue())){
                            throw new ExceptionUtil("该任务节点驳回时候设定了驳回后执行人为“重新指定人”，可是人员为空！");
                        }
                    }
                    if(rejectExecutor.equals(ActivitiUtil.ACT_CODE_30)){//采用原节点配置规则选举人（暂时废弃 其实还是通过前端获取用户设置）
                        if(StringUtil.isEmpty(lcReceiveNParam.getMutilValue())){
                            throw new ExceptionUtil("该任务节点驳回时候设定了驳回后执行人为“采用原节点配置规则选举人”，可是人员为空！");
                        }
                    }
                }
            }
        }else{//默认按目标节点退回，并按原节点执行人设置
            LcReceiveParam par = new LcReceiveParam();
            par.setActivityId(lcReceiveNParam.getActivityId());
            par.setProcessInstanceId(historicTaskInstance.getProcessInstanceId());
            multiInstance = activitiUtil.validateNodeIsMultiInstance(par);
            if(multiInstance){//驳回的目标节点为会签节点则独立处理
                //获取目标节点扩展属性
                targetLcNodeAttribute =getNodeAttribute(deploymentId,lcReceiveNParam.getActivityId());
                Map<String,Object> map = lcReceiveNParam.getVariables();
                if(CollectionUtil.isEmpty(map)){
                    map = new HashMap<>();
                    LcHisMutil lcHisMutil = new LcHisMutil();
                    lcHisMutil.setActivityId(lcReceiveNParam.getActivityId());
                    lcHisMutil.setProInstId(historicTaskInstance.getProcessInstanceId());
                    if(null != targetLcNodeAttribute && !StringUtil.isEmpty(targetLcNodeAttribute.getMutilKey())){//目标节点为会签节点 必须通过变量中获取key
                        map.put(targetLcNodeAttribute.getMutilKey(), commonMutil(lcHisMutil));//传递变量值
                        lcReceiveNParam.setVariables(map);
                    }
                }
            }else{//普通节点
                mutilValueMap = getOldMutilValue(lcReceiveNParam,historicTaskInstance,false);
            }
        }

        BaseResult baseResult = activitiUtil.jump(lcReceiveNParam);
        /*
        List<Task> tasks = activitiUtil.findTaskListByInstanceId(historicTaskInstance.getProcessInstanceId());
        for(Task task: tasks){
            String nodeId = task.getTaskDefinitionKey();//节点编号
            if(multiInstance){
                break;//会签节点无需重新指定人（原因在上述跳转的时候已经将人员设置了）
            }
            //普通节点重新指定人
            if(nodeId.equals(lcReceiveNParam.getActivityId())){
                if(null != mutilValueMap.get("mutilValue")){//处理办理人单个
                    boolean r = activitiUtil.setAssignee(task.getId(),""+mutilValueMap.get("mutilValue"));
                    if(!r){
                        log.info("驳回节点时，重新设置审批人失败");
                        return new BaseResult("驳回节点时，重新设置审批人失败",false);
                    }
                }
                break;
            }
        }*/

        String mutilValue = ""+mutilValueMap.get("mutilValue");
        List<LcReceiveParam> lcReceiveParams = lcReceiveNParam.getLcReceiveParams();
        if(!CollectionUtil.isEmpty(lcReceiveParams)){
            for(int i= 0; i < lcReceiveParams.size(); i++){
                LcReceiveParam lcReceiveParam = lcReceiveParams.get(i);
                if(StringUtil.isEmpty(lcReceiveParam.getMutilValue())){
                    if(StringUtil.isEmpty(mutilValue)){
                        log.info("未能找到驳回后的原节点处理人,{}",lcReceiveParam);
                        throw new ExceptionUtil("未能找到驳回后的原节点处理人");
                    }
                    lcReceiveNParam.getLcReceiveParams().get(i).setNeedHandledTransactor(true);
                    lcReceiveNParam.getLcReceiveParams().get(i).setMutilValue(mutilValue);
                }
            }
        }
        log.info("驳回后的原节点处理人,{}",lcReceiveNParam);
        setAssignee(historicTaskInstance,lcReceiveNParam);//设置处理人
        //返回流程实例是否结束
        ActivityProcessStatusEntity activityProcessStatusEntity = checkStatus(historicTaskInstance.getProcessInstanceId());
        activityProcessStatusEntity.setCurrentActivityId(currentActivityId);
        activityProcessStatusEntity.setCurrentName(currentName);
        activityProcessStatusEntity.setAccount(mutilValue);
        activityProcessStatusEntity.setMutilComplate(mutilComplate);
        baseResult.setData(activityProcessStatusEntity);
        return baseResult;
    }

    /**
     * 转办
     * @param lcReceiveNParam
     * @return
     */
    public BaseResult transfer(LcReceiveNParam lcReceiveNParam){
        lcReceiveNParam.setBehavior(ActivitiUtil.BEHAVIOR_70);
        if(StringUtil.isEmpty(lcReceiveNParam.getTaskId())){
            throw new ExceptionUtil("未能获取到任务id");
        }

        if(lcReceiveNParam.isSetOwner()){//如果需要指定任务所属人 则进行设置 将来可以找到
            activitiUtil.setOwner(lcReceiveNParam.getTaskId(),lcReceiveNParam.getOwnerId());
        }
        HistoricTaskInstance historicTaskInstance = activitiUtil.getTaskById(lcReceiveNParam.getTaskId());
        if(null ==historicTaskInstance){
            throw new ExceptionUtil("转办任务时，任务不存在");
        }
        persistenceAppro(historicTaskInstance,lcReceiveNParam);//持久化日志
        String mutilValue = null;
        if(StringUtil.isEmpty(lcReceiveNParam.getMutilValue())){
            if(CollectionUtil.isEmpty(lcReceiveNParam.getLcReceiveParams())){
                throw new ExceptionUtil("目标参数不存在");
            }
            mutilValue = lcReceiveNParam.getLcReceiveParams().get(0).getMutilValue();
        }else{
            mutilValue = lcReceiveNParam.getMutilValue();
        }
        if(StringUtil.isEmpty(mutilValue)){
            throw new ExceptionUtil("转办人不存在");
        }
        lcReceiveNParam.setMutilValue(mutilValue);//目标节点
        boolean b = activitiUtil.setAssignee(lcReceiveNParam.getTaskId(), mutilValue);
        BaseResult baseResult = new BaseResult();
        if(!b){
            throw new ExceptionUtil("转办失败");
        }
        String currentActivityId =historicTaskInstance.getTaskDefinitionKey();
        String currentName = historicTaskInstance.getName();//当前审批任务节点名称
        ActivityProcessStatusEntity activityProcessStatusEntity = checkStatus(historicTaskInstance.getProcessInstanceId());
        activityProcessStatusEntity.setCurrentActivityId(currentActivityId);
        activityProcessStatusEntity.setCurrentName(currentName);
        baseResult.setData(activityProcessStatusEntity);
        return baseResult;
    }

    /**
     * 加签
     * @param lcReceiveNParam
     * @return
     */
    public synchronized BaseResult sign(LcReceiveNParam lcReceiveNParam){
        lcReceiveNParam.setBehavior(ActivitiUtil.BEHAVIOR_90);
        if(StringUtil.isEmpty(lcReceiveNParam.getTaskId())){
            throw new ExceptionUtil("未能获取到任务id");
        }
        HistoricTaskInstance historicTaskInstance = activitiUtil.getTaskById(lcReceiveNParam.getTaskId());
        if(null ==historicTaskInstance){
            throw new ExceptionUtil("加签时，任务不存在");
        }

        Map<String,Object> condition = new HashMap<>();
        condition.put("procInstId",historicTaskInstance.getProcessInstanceId());
        condition.put("taskDefKey",historicTaskInstance.getTaskDefinitionKey());
        List<LcSign> lcSignList = lcSignService.getLcSignListByCondition(condition);

        if(CollectionUtil.isEmpty(lcSignList)){
            throw new ExceptionUtil("未能获取到当前节点会签记录");
        }

        persistenceAppro(historicTaskInstance,lcReceiveNParam);//持久化日志
        LcMutilEntity lcMutilEntity = null;//只需要记录最后一次会签
        List<LcReceiveParam> lcReceiveParams = lcReceiveNParam.getLcReceiveParams();
        if(!CollectionUtil.isEmpty(lcReceiveParams)){
            for(LcReceiveParam lcReceiveParam: lcReceiveParams){
                lcReceiveParam.setTaskId(lcReceiveNParam.getTaskId());
                if(!StringUtil.isEmpty(lcReceiveParam.getMutilValue())){
                    String[] mutilValue = lcReceiveParam.getMutilValue().split(",");
                    for(String mv : mutilValue){
                        lcReceiveNParam.setMutilValue(mv);
                        lcMutilEntity = activitiUtil.mutilParallel(lcReceiveNParam);
                        updateActHiTaskInst(lcMutilEntity);
                    }
                }else{
                    lcMutilEntity = activitiUtil.mutilParallel(lcReceiveNParam);
                    updateActHiTaskInst(lcMutilEntity);
                }
            }
        }
        LcSign lcSign = lcSignList.get(0);
        lcSign.setNrOfInstances(lcMutilEntity.getNrOfInstances());
        lcSign.setUpdateTime(getDate());
        lcSign.setNrOfCompletedInstances(lcMutilEntity.getNrOfCompletedInstances());
        int i = lcSignService.updateLcSign(lcSign);
        log.info("会签节点历史记录更新结果：{}",i);
        ActivityProcessStatusEntity activityProcessStatusEntity = checkStatus(historicTaskInstance.getProcessInstanceId());
        return new BaseResult("加签成功",true,activityProcessStatusEntity);
    }

    /**
     * 弃权
     * @param lcReceiveNParam
     * @return
     */
    public BaseResult waiver(LcReceiveNParam lcReceiveNParam){
        lcReceiveNParam.setBehavior(ActivitiUtil.BEHAVIOR_30);
        return agreement(lcReceiveNParam);
    }

    /**
     * 委派
     * @param lcReceiveNParam
     * @return
     */
    public BaseResult delegateTask(LcReceiveNParam lcReceiveNParam){

        lcReceiveNParam.setBehavior(ActivitiUtil.BEHAVIOR_80);

        if(StringUtil.isEmpty(lcReceiveNParam.getTaskId())){
            throw new ExceptionUtil("未能获取到任务id");
        }
        if(StringUtil.isEmpty(lcReceiveNParam.getOwnerId())){
            throw new ExceptionUtil("未能获取到委派人");
        }
        if(lcReceiveNParam.isSetOwner()){//如果需要指定任务所属人 则进行设置 将来可以找到
            activitiUtil.setOwner(lcReceiveNParam.getTaskId(),lcReceiveNParam.getOwnerId());
        }
        if(StringUtil.isEmpty(lcReceiveNParam.getTaskId())){
            throw new ExceptionUtil("未能获取到任务id");
        }
        HistoricTaskInstance historicTaskInstance = activitiUtil.getTaskById(lcReceiveNParam.getTaskId());
        if(null ==historicTaskInstance){
            throw new ExceptionUtil("委派任务时，任务不存在");
        }
        persistenceAppro(historicTaskInstance,lcReceiveNParam);//持久化日志
        return new BaseResult(activitiUtil.delegateTask(lcReceiveNParam.getTaskId(), lcReceiveNParam.getMutilValue()));
    }

    /**
     * 催办
     * @param lcReceiveNParam
     * @return
     */
    public BaseResult urge(LcReceiveNParam lcReceiveNParam){
        lcReceiveNParam.setBehavior(ActivitiUtil.BEHAVIOR_100);
        if(StringUtil.isEmpty(lcReceiveNParam.getTaskId())){
            throw new ExceptionUtil("未能获取到任务id");
        }
        HistoricTaskInstance historicTaskInstance = activitiUtil.getTaskById(lcReceiveNParam.getTaskId());
        if(null ==historicTaskInstance){
            throw new ExceptionUtil("催办任务时，任务不存在");
        }
        persistenceAppro(historicTaskInstance,lcReceiveNParam);//持久化日志
        return BaseResult.success();
    }

    /**
     * 终止流程
     * @param lcReceiveNParam
     * @return
     */
    public BaseResult termination(LcReceiveNParam lcReceiveNParam){
        lcReceiveNParam.setBehavior(ActivitiUtil.BEHAVIOR_50);
        if(StringUtil.isEmpty(lcReceiveNParam.getTaskId()) && StringUtil.isEmpty(lcReceiveNParam.getProcessInstanceId())){
            throw new ExceptionUtil("终止流程时，未能获取到任务id或流程实例id");
        }
        BaseResult baseResult = null;
        if(!StringUtil.isEmpty(lcReceiveNParam.getTaskId())){//通过流程任务终止时需要记录日志
            HistoricTaskInstance historicTaskInstance = activitiUtil.getTaskById(lcReceiveNParam.getTaskId());
            if(null == historicTaskInstance){
                throw new ExceptionUtil("终止流程时，任务不存在");
            }
            persistenceAppro(historicTaskInstance,lcReceiveNParam);//终止流程日志
            baseResult = activitiUtil.termination(lcReceiveNParam);
            ActivityProcessStatusEntity activityProcessStatusEntity = new ActivityProcessStatusEntity(historicTaskInstance.getProcessInstanceId(),true);
            baseResult.setData(activityProcessStatusEntity);
        }
        if(!StringUtil.isEmpty(lcReceiveNParam.getProcessInstanceId())){//通过流程实例终止 无需记录日志
            String[] array = lcReceiveNParam.getProcessInstanceId().split(",");
            for(String instId:array){
                LcReceiveNParam param = new LcReceiveNParam();
                param.setProcessInstanceId(instId);
                baseResult = activitiUtil.termination(param);
                if(!baseResult.getSuccess()){//如果存在一个失败则直接全部回滚
                    throw new ExceptionUtil("根据流程实例批量终止流程异常");
                }
            }
            ActivityProcessStatusEntity activityProcessStatusEntity = new ActivityProcessStatusEntity(lcReceiveNParam.getProcessInstanceId(),true);
            baseResult.setData(activityProcessStatusEntity);
        }
        return baseResult;
    }

    /**
     * 设置归属人
     * @param lcReceiveNParam
     * @return
     */
    public BaseResult setOwner(LcReceiveNParam lcReceiveNParam){
        lcReceiveNParam.setBehavior(ActivitiUtil.BEHAVIOR_110);
        if(StringUtil.isEmpty(lcReceiveNParam.getTaskId())){
            throw new ExceptionUtil("未能获取到任务id");
        }
        if(StringUtil.isEmpty(lcReceiveNParam.getMutilValue())){
            throw new ExceptionUtil("未能获取到所属人");
        }
        HistoricTaskInstance historicTaskInstance = activitiUtil.getTaskById(lcReceiveNParam.getTaskId());
        if(null == historicTaskInstance){
            throw new ExceptionUtil("设置归属人时，任务不存在");
        }
        persistenceAppro(historicTaskInstance,lcReceiveNParam);//设置归属人记录日志
        return new BaseResult(activitiUtil.setOwner(lcReceiveNParam.getTaskId(), lcReceiveNParam.getMutilValue()));
    }

    /**
     * 根据流程实例id查找流程实例下任务节点
     * @param procInstId
     * @return
     */
    public BaseResult<List<UserTask>> getUserTaskListByProcessInstanceId(String procInstId){
        List<UserTask> userTasks = activitiUtil.getUserTaskByProcessInstanceId(procInstId);
        return new BaseResult(userTasks);
    }

//    /**
//     * 根据当前任务节点任意跳转节点
//     * @param lcReceiveNParam
//     * @return
//     */
//    public BaseResult executeJump(LcReceiveNParam lcReceiveNParam){
//        lcReceiveNParam.setBehavior(ActivitiUtil.BEHAVIOR_60);
//        if(StringUtil.isEmpty(lcReceiveNParam.getTaskId())){
//            throw new ExceptionUtil("未能获取到任务id");
//        }
//        if(StringUtil.isEmpty(lcReceiveNParam.getActivityId())){
//            if(CollectionUtil.isEmpty(lcReceiveNParam.getLcReceiveParams())){
//                throw new ExceptionUtil("目标参数不存在");
//            }
//            lcReceiveNParam.setActivityId( lcReceiveNParam.getLcReceiveParams().get(0).getActivityId());//目标节点
//        }
//        HistoricTaskInstance historicTaskInstance = activitiUtil.getTaskById(lcReceiveNParam.getTaskId());
//        persistenceAppro(historicTaskInstance,lcReceiveNParam);//执行跳转节点记录日志
//        if(null == historicTaskInstance){
//            throw new ExceptionUtil("流程实例不存在");
//        }
//        String currentActivityId = historicTaskInstance.getTaskDefinitionKey();
//        BaseResult baseResult = activitiUtil.jump(lcReceiveNParam);
//        setAssignee(historicTaskInstance,lcReceiveNParam);//设置处理人
//        ActivityProcessStatusEntity activityProcessStatusEntity = checkStatus(historicTaskInstance.getProcessInstanceId());
//        activityProcessStatusEntity.setCurrentActivityId(currentActivityId);
//        baseResult.setData(activityProcessStatusEntity);
//        return baseResult;
//    }

    /**
     * 根据当前任务节点任意跳转节点
     * 自由跳转时强制采用跳转模式 不存在采用完成动作
     *
     * @param lcReceiveNParam
     * @return
     */
    public BaseResult executeJump(LcReceiveNParam lcReceiveNParam){
        lcReceiveNParam.setBehavior(ActivitiUtil.BEHAVIOR_60);
        if(StringUtil.isEmpty(lcReceiveNParam.getTaskId())){
            throw new ExceptionUtil("未能获取到任务id");
        }
        if(StringUtil.isEmpty(lcReceiveNParam.getActivityId())){
            if(CollectionUtil.isEmpty(lcReceiveNParam.getLcReceiveParams())){
                throw new ExceptionUtil("目标参数不存在");
            }
            lcReceiveNParam.setActivityId( lcReceiveNParam.getLcReceiveParams().get(0).getActivityId());//目标节点
        }

        boolean res = true;
        HistoricTaskInstance historicTaskInstance = null;
        Map<String,Object> map = new HashMap<>();
        List<LcReceiveParam> lcReceiveParamList = lcReceiveNParam.getLcReceiveParams();
        String deploymentId = activitiUtil.getDeploymentIdByTaskId(lcReceiveNParam.getTaskId());//根据当前任务id查找部署编号
        historicTaskInstance = activitiUtil.getTaskById(lcReceiveNParam.getTaskId());//根据当前任务id查找流程实例
        String currentActivityId = null;
        String currentName = null;
        if(null != historicTaskInstance){
            currentActivityId = historicTaskInstance.getTaskDefinitionKey();//当前审批节点id
            currentName = historicTaskInstance.getName();//当前审批任务节点名称
        }
        String targetActivityId = lcReceiveNParam.getLcReceiveParams().get(0).getActivityId();
        if(StringUtil.isEmpty(targetActivityId)){
            throw new ExceptionUtil("未能获取到目标节点");
        }

        if(!CollectionUtil.isEmpty(lcReceiveParamList)){
            for(LcReceiveParam lcReceiveParam :lcReceiveParamList){
                if(!StringUtil.isEmpty(deploymentId) && null != historicTaskInstance){
                    LcDeploymentHis lcDeploymentHis = lcDeploymentHisService.getLcDeploymentHisByDeploymentId(deploymentId);
                    if(null != lcDeploymentHis){

                        //获取目标节点
                        LcReceiveParam param = new LcReceiveParam();
                        param.setProcessInstanceId(historicTaskInstance.getProcessInstanceId());
                        if(!StringUtil.isEmpty(lcReceiveParam.getActivityId())){
                            param.setActivityId(lcReceiveParam.getActivityId());
                        }else{
                            param.setActivityId(targetActivityId);
                            lcReceiveParam.setActivityId(targetActivityId);//设定目标节点
                        }
                        boolean mutil = activitiUtil.validateNodeIsMultiInstance(param);

                        //如果是会签节点并且会签集合不存在则抛异常
                        if(StringUtil.isEmpty(lcReceiveParam.getMutilValue()) && mutil){
                            throw new ExceptionUtil("目标节点为会签节点，必须指定办理人");
                        }

                        ActivityImpl activityImpl = activitiUtil.getActivityImpl(param);//查找出目标节点

                        //节点的扩展属性（用于做逻辑使用）
                        NodeAttributeParam nodeAttributeParam = new NodeAttributeParam();
                        nodeAttributeParam.setHid_(lcDeploymentHis.getId());
                        nodeAttributeParam.setNodeId(lcReceiveParam.getActivityId());
                        LcNodeAttribute lcNodeAttributeTarget = lcNodeAttributeService.getLcNodeAttribute(nodeAttributeParam);
                        if(null != lcNodeAttributeTarget){
                            String mutilKey = lcNodeAttributeTarget.getMutilKey();
                            if(!StringUtil.isEmpty(mutilKey) && mutil){//如果会签采用扩展表达式则优先使用扩展属性中变量名
                                List<String> list = Arrays.asList(lcReceiveParam.getMutilValue().split(","));
                                map.put(mutilKey, list);//传递变量值
                                try {
                                    addBatchLcHisMutil(list,historicTaskInstance.getProcessInstanceId(),activityImpl);//创建会签节点人员
                                }catch (Exception e){
                                    log.error("创建会签节点人员失败：{}",e);
                                    throw new ExceptionUtil("创建会签节点人员失败,{}",e);
                                }
                                TaskDefinition taskDefinition = null;
                                if(((ActivityImpl) activityImpl).getActivityBehavior() instanceof SequentialMultiInstanceBehavior){//会签多实例串行
                                    SequentialMultiInstanceBehavior sequentialMultiInstanceBehavior = ((SequentialMultiInstanceBehavior) ((ActivityImpl) activityImpl).getActivityBehavior());
                                    taskDefinition = ((UserTaskActivityBehavior)sequentialMultiInstanceBehavior.getInnerActivityBehavior()).getTaskDefinition();
                                }else if(((ActivityImpl) activityImpl).getActivityBehavior() instanceof ParallelMultiInstanceBehavior){//会签多实例并行
                                    ParallelMultiInstanceBehavior parallelMultiInstanceBehavior =  ((ParallelMultiInstanceBehavior) ((ActivityImpl) activityImpl).getActivityBehavior());
                                    taskDefinition = ((UserTaskActivityBehavior)parallelMultiInstanceBehavior.getInnerActivityBehavior()).getTaskDefinition();
                                }else if(((ActivityImpl) activityImpl).getActivityBehavior() instanceof MultiInstanceActivityBehavior){
                                    MultiInstanceActivityBehavior multiInstanceActivityBehavior =  ((MultiInstanceActivityBehavior) ((ActivityImpl) activityImpl).getActivityBehavior());
                                    taskDefinition = ((UserTaskActivityBehavior)multiInstanceActivityBehavior.getInnerActivityBehavior()).getTaskDefinition();
                                }
                                if(null != taskDefinition && null == taskDefinition.getAssigneeExpression()){//如果会签节点中没有办理人变量没有设置 则标记为需要重新动态分配
                                    lcReceiveParam.setNeedHandledTransactor(true);
                                }
                            }else{
                                if ("userTask".equals(activityImpl.getProperty("type")) && ((ActivityImpl) activityImpl).getActivityBehavior() instanceof UserTaskActivityBehavior){
                                    TaskDefinition taskDefinition = ((UserTaskActivityBehavior) ((ActivityImpl) activityImpl).getActivityBehavior()).getTaskDefinition();
                                    if(null != taskDefinition.getAssigneeExpression()){//如果审批人中有变量 则无需标记处理人
                                        String expression  = taskDefinition.getAssigneeExpression().getExpressionText().replace("${","").replace("}","");
                                        map.put(expression, lcReceiveParam.getMutilValue());//传递变量值
                                    }else{
                                        //普通节点
                                        lcReceiveParam.setNeedHandledTransactor(true);
                                    }
                                }else{
                                    //普通节点
                                    lcReceiveParam.setNeedHandledTransactor(true);
                                }
                            }
                        }else{
                            if ("userTask".equals(activityImpl.getProperty("type")) && ((ActivityImpl) activityImpl).getActivityBehavior() instanceof UserTaskActivityBehavior){
                                TaskDefinition taskDefinition = ((UserTaskActivityBehavior) ((ActivityImpl) activityImpl).getActivityBehavior()).getTaskDefinition();
                                if(null != taskDefinition.getAssigneeExpression() && !StringUtil.isEmpty(taskDefinition.getAssigneeExpression().getExpressionText())){//如果审批人中有变量 则无需标记处理人
                                    String expression  = taskDefinition.getAssigneeExpression().getExpressionText().replace("${","").replace("}","");
                                    map.put(expression, lcReceiveParam.getMutilValue());//传递变量值
                                }else{
                                    //普通节点
                                    lcReceiveParam.setNeedHandledTransactor(true);
                                }
                            }else{
                                //普通节点
                                lcReceiveParam.setNeedHandledTransactor(true);
                            }
                        }
                    }
                }
            }
        }
        persistenceAppro(historicTaskInstance,lcReceiveNParam);//持久化日志
        lcReceiveNParam.setVariables(map);//设置变量
        lcReceiveNParam.setActivityId(targetActivityId);
        activitiUtil.jump(lcReceiveNParam);//注意此时跳转后 不需要终止 还是要继续执行下面命令为了重新分配人等等

        log.info("执行完成任务动作,分配节点执行人");
        setAssignee(historicTaskInstance,lcReceiveNParam);//设置处理人

        //返回流程实例是否结束
        ActivityProcessStatusEntity activityProcessStatusEntity = checkStatus(historicTaskInstance.getProcessInstanceId());
        activityProcessStatusEntity.setCurrentActivityId(currentActivityId);
        activityProcessStatusEntity.setCurrentName(currentName);
        BaseResult baseResult = new BaseResult();
        baseResult.setData(activityProcessStatusEntity);
        baseResult.setSuccess(res);
        return baseResult;
    }

    /**
     * 根据当前任务Id查询可以驳回的任务节点
     * @param taskId
     * @return
     */
    public BaseResult findCanBackActivity(String taskId){
        List<LcTask> lcTasks = new ArrayList<>();
        List<ActivityImpl> activities = activitiUtil.findCanBackActivity(taskId);
        if(!CollectionUtils.isEmpty(activities)){
            for(ActivityImpl activity: activities){
                LcTask lcTask = new LcTask();
                if(!CollectionUtils.isEmpty(activity.getProperties())){
                    if(null != activity.getProperties().get("name")){
                        lcTask.setName(""+activity.getProperties().get("name"));
                    }
                }
                lcTask.setTaskId(activity.getId());
                lcTasks.add(lcTask);
            }
        }
        return new BaseResult(lcTasks);
    }

    /**
     * 根据任务Id查询下一个节点
     * @param taskId
     * @return
     */
    public BaseResult getLcNextNode(String taskId){
        Map<String,Object> condition = new HashMap<>();
        List<LcTask> lcTasks = new ArrayList<>();
        List<TaskDefinition> taskDefinitionList = activitiUtil.getNextTaskDefinitionList(taskId,condition);
        if(!CollectionUtils.isEmpty(taskDefinitionList)){
            for(TaskDefinition taskDefinition: taskDefinitionList){
                LcTask lcTask = new LcTask();
                lcTask.setName(""+taskDefinition.getNameExpression());
                lcTask.setTaskId(taskDefinition.getKey());
                lcTask.setNodeType("用户任务");
                LcReceiveParam lcReceiveParam = new LcReceiveParam();
                HistoricTaskInstance historicTaskInstance = activitiUtil.getTaskById(taskId);
                lcReceiveParam.setProcessInstanceId(historicTaskInstance.getProcessInstanceId());
                lcReceiveParam.setActivityId(taskDefinition.getKey());
                boolean mutil = activitiUtil.validateNodeIsMultiInstance(lcReceiveParam);
                if(mutil){
                    lcTask.setMutil(ActivitiUtil.ACT_CODE_20);
                }else{
                    lcTask.setMutil(ActivitiUtil.ACT_CODE_10);
                }
                lcTasks.add(lcTask);
            }
        }
        return new BaseResult(lcTasks);
    }

    /**
     * 查找当前任务所在节点按流程图走向查找上级节点
     * @param lcReceiveNParam
     * @return
     */
    public BaseResult previousNode(LcReceiveNParam lcReceiveNParam){
        List<UserTask> taskList = activitiUtil.previousNode(lcReceiveNParam);
        return new BaseResult(taskList);
    }

    /**
     * 查找行为属性
     * @param taskId
     * @return
     */
    public BaseResult getActivityBehavior(String taskId){
        ActivityImpl activity = activitiUtil.getActivityImpl(taskId);
        if(null == activity){
            return new BaseResult("未能获取到节点",false);
        }
        BehaviorEntity behaviorEntity = activitiUtil.getMultiBehavior(activity);
        return new BaseResult(behaviorEntity);
    }

    /**
     * 查找行为属性
     * @param lcReceiveParam
     * @return
     */
    public BaseResult getActivityBehavior(LcReceiveParam lcReceiveParam){
        ActivityImpl activity = activitiUtil.getActivityImpl(lcReceiveParam);
        if(null == activity){
            return new BaseResult("未能获取到节点",false);
        }
        BehaviorEntity behaviorEntity = activitiUtil.getMultiBehavior(activity);
        return new BaseResult(behaviorEntity);
    }

    /**
     * 查询当前任务节点流出线指定属性集合（可用于在办理任务节点操作进行驳回或通过）
     * @param taskId
     * @param attribute
     * @return
     */
    public BaseResult getOutTransListByTaskId(String taskId,String attribute){
        return new BaseResult(activitiUtil.getOutTransListByTaskId(taskId,attribute));
    }

    /**
     * 查询当前任务流出线名称集合
     * @param taskId
     * @return
     */
    public BaseResult getOutTransListByTaskId(String taskId){
        return new BaseResult(activitiUtil.getOutTransListByTaskId(taskId));
    }

    /**
     * 根据任务Id查询自定义节点属性
     * @param taskId
     * @return
     */
    public BaseResult<LcNodeAttribute> getLcNodeAttribute(String taskId){
        return new BaseResult(getLcNodeAttributeByTaskId(taskId));
    }

    /**
     * 判断节点是否为会签节点,条件可以单独使用taskId,也可以使用流程实例：processInstanceId+节点id：activityId（多实例）
     * @param lcReceiveNParam
     * @return
     */
    public BaseResult multi(LcReceiveNParam lcReceiveNParam){
        LcReceiveParam lcReceiveParam = new LcReceiveParam();
        lcReceiveParam.setTaskId(lcReceiveNParam.getTaskId());
        lcReceiveParam.setProcessInstanceId(lcReceiveNParam.getProcessInstanceId());
        boolean res = activitiUtil.validateNodeIsMultiInstance(lcReceiveParam);
        return new BaseResult(res);
    }

    /**
     * 查询业务Key
     * @param taskId
     * @return
     */
    public BaseResult getBusinessKey(String taskId){
        return new BaseResult(activitiUtil.getBusinessKey(taskId));
    }

    /**
     * 查询设置Task变量（如在处理当前任务设置变量 在下一个节点中可以获取该变量）
     * @param taskId
     * @param key
     * @return
     */
    public BaseResult getTaskVariable(String taskId,String key){
        return new BaseResult(activitiUtil.getTaskVariable(taskId,key));
    }

    /**
     * 根据任务Id获取当前任务节点流出线指定属性集合
     * @param taskId
     * @return
     */
    public BaseResult getTaskVariable(String taskId){
        return new BaseResult(activitiUtil.getTaskVariable(taskId));
    }

    /**
     * 设置Task变量（如在处理当前任务设置变量 在下一个节点中可以获取该变量）
     * @param lcReceiveNParam
     * @return
     */
    public BaseResult setTaskVariable(LcReceiveNParam lcReceiveNParam){
        return new BaseResult(activitiUtil.setTaskVariable(lcReceiveNParam.getTaskId(),lcReceiveNParam.getVariables()));
    }

    /**
     * 向组任务中添加成员
     * @param lcReceiveNParam
     * @return
     */
    public BaseResult addGroupUser(LcReceiveNParam lcReceiveNParam){
        return new BaseResult(activitiUtil.addGroupUser(lcReceiveNParam.getTaskId(), lcReceiveNParam.getMutilValue()));
    }

    /**
     * 向组任务中删除成员
     * @param lcReceiveNParam
     * @return
     */
    public BaseResult deleteGroupUser(LcReceiveNParam lcReceiveNParam){
        return new BaseResult(activitiUtil.deleteGroupUser(lcReceiveNParam.getTaskId(), lcReceiveNParam.getMutilValue()));
    }

    /**
     * 查找流程实例下任务
     * @param processInstanceId
     * @return
     */
    public BaseResult<List<LcTask>> getLcTaskListByProcessInstanceId(String processInstanceId){
        List<LcTask> lcTasks = new ArrayList<>();
        List<HistoricTaskInstance> historicTaskInstances = activitiUtil.getHistoricTaskInstanceListByProcessInstanceId(processInstanceId);
        for(HistoricTaskInstance historicTaskInstance: historicTaskInstances){
            LcTask lcTask = new LcTask();
            lcTask.setTaskId(historicTaskInstance.getId());
            lcTask.setName(historicTaskInstance.getName());
            lcTasks.add(lcTask);
        }
        return new BaseResult(lcTasks);
    }

    /**
     * 挂起流程实例
     * @param lcReceiveNParam
     * @return
     */
    public BaseResult suspendProcess(LcReceiveNParam lcReceiveNParam){
        if(null == lcReceiveNParam){
            throw new ExceptionUtil("参数对象为空");
        }
        if(StringUtil.isEmpty(lcReceiveNParam.getTaskId())){
            throw new ExceptionUtil("未能获取到任务id");
        }
        HistoricTaskInstance historicTaskInstance = activitiUtil.getTaskById(lcReceiveNParam.getTaskId());
        if(null ==historicTaskInstance){
            throw new ExceptionUtil("挂起流程时，任务不存在");
        }
        persistenceAppro(historicTaskInstance,lcReceiveNParam);//持久化日志

        boolean flag = activitiUtil.suspendProcessInstanceById(historicTaskInstance.getProcessInstanceId());
        if(flag){
            return new BaseResult("挂起流程实例成功",flag,new ActivityProcessStatusEntity(historicTaskInstance.getProcessInstanceId(),false,historicTaskInstance.getName()));
        }
        return new BaseResult("挂起流程实例失败",flag,new ActivityProcessStatusEntity(historicTaskInstance.getProcessInstanceId(),false,historicTaskInstance.getName()));
    }

    /**
     * 激活流程实例
     * @param lcReceiveNParam
     * @return
     */
    public BaseResult activateProcess(LcReceiveNParam lcReceiveNParam){
        if(null == lcReceiveNParam){
            throw new ExceptionUtil("参数对象为空");
        }
        if(StringUtil.isEmpty(lcReceiveNParam.getTaskId())){
            throw new ExceptionUtil("未能获取到任务id");
        }
        HistoricTaskInstance historicTaskInstance = activitiUtil.getTaskById(lcReceiveNParam.getTaskId());
        if(null ==historicTaskInstance){
            throw new ExceptionUtil("激活流程时，任务不存在");
        }
        persistenceAppro(historicTaskInstance,lcReceiveNParam);//持久化日志

        boolean flag = activitiUtil.activateProcessInstanceById(historicTaskInstance.getProcessInstanceId());
        if(flag){
            return new BaseResult("激活流程实例成功",flag,new ActivityProcessStatusEntity(historicTaskInstance.getProcessInstanceId(),false,historicTaskInstance.getName()));
        }
        return new BaseResult("激活流程实例失败",flag,new ActivityProcessStatusEntity(historicTaskInstance.getProcessInstanceId(),false,historicTaskInstance.getName()));
    }

    /**
     * 根据任务id查询当前节点及目标节点属性
     * @param taskId
     * @return
     */
    public BaseResult<LcAttributeNEntity> getLcAttribute(String taskId, Map<String,Object> condition){
        Task task = activitiUtil.getTaskByTaskId(taskId);
        if(null == task){
            log.warn("当前任务不存在,{}",taskId);
            throw new ExceptionUtil("当前任务不存在！");
        }
        LcAttributeNEntity lcAttributeNEntity = new LcAttributeNEntity();//当前节点临时对象
        lcAttributeNEntity.setTaskId(taskId);//设置当前节点任务
        lcAttributeNEntity.setSuspended(task.isSuspended());//当前任务是否挂起
        lcAttributeNEntity.setProcessInstanceId(task.getProcessInstanceId());//当前实例
        LcReceiveParam param = new LcReceiveParam();
        param.setTaskId(taskId);
        boolean currentMutil = activitiUtil.validateNodeIsMultiInstance(param);
        if(currentMutil){
            lcAttributeNEntity.setMutil(ActivitiUtil.ACT_CODE_20);//当前节点会签
        }else{
            lcAttributeNEntity.setMutil(ActivitiUtil.ACT_CODE_10);//当前节点非会签
        }

        LcNodeAttribute lcNodeAttribute = getLcNodeAttributeByTaskId(taskId);//当前节点扩展属性
        lcAttributeNEntity.setPcFormUri(lcNodeAttribute.getPcFormUri());//当前节点PC表单
        lcAttributeNEntity.setMobileFormUri(lcNodeAttribute.getMobileFormUri());//当前移动端表单
        List<LcAttributeEntity> lcAttributeEntities = new ArrayList<>();//目标节点属性集合
        if(null == lcNodeAttribute || CollectionUtil.isEmpty(lcNodeAttribute.getLcNodeBtns())){
            commonAttribute(taskId,condition,lcAttributeEntities);
        }else{
            lcAttributeNEntity.setNodeFormFieldList(lcNodeAttribute.getNodeFormField());//设置当前节点字段
            lcAttributeNEntity.setAttr(lcNodeAttribute.getAttr());//扩展属性
            lcAttributeNEntity.setOpinion(lcNodeAttribute.getOpinion());//提交意见:10无需提交意见 20必须提交意见，缺省为：无需提交意见
            List<LcNodeBtn> lcNodeBtns = lcNodeAttribute.getLcNodeBtns();
            if(!CollectionUtil.isEmpty(lcNodeBtns)){//如果自定义按钮存在则
                for(LcNodeBtn lcNodeBtn: lcNodeBtns){
                    List<LcJumpRules> lcJumpRules = lcNodeBtn.getLcJumpRules();
                    if(!CollectionUtil.isEmpty(lcJumpRules)){
                        for(LcJumpRules rules: lcJumpRules){
                            LcAttributeEntity lcAttributeEntity = new LcAttributeEntity();//目标节点对象
                            lcAttributeEntity.setBehavior(lcNodeBtn.getLcBtn() == null ?ActivitiUtil.BEHAVIOR_10:lcNodeBtn.getLcBtn().getBehavior());
                            lcAttributeEntity.setActivityId(rules.getTargetNodeId());//目标节点id
                            lcAttributeEntity.setActivityName(rules.getNodeName());//目标节点名称
                            lcAttributeEntity.setLabel_(lcNodeBtn.getLabel_());
                            lcAttributeEntity.setBtnAction(lcNodeBtn.getBtnAction());
                            lcAttributeEntity.setNodeBtnId(lcNodeBtn.getId());//nodeBtn对象中id（非btn对象中id）
                            lcAttributeEntity.setLcBtn(lcNodeBtn.getLcBtn());//按钮对象

                            //处理目标节点办理人规则
                            NodeAttributeParam nodeAttributeParam = new NodeAttributeParam();
                            nodeAttributeParam.setHid_(lcNodeAttribute.getHid_());
                            nodeAttributeParam.setNodeId(rules.getTargetNodeId());
                            LcNodeAttribute attribute = lcNodeAttributeService.getLcNodeAttribute(nodeAttributeParam);
                            if(null != attribute){
                                lcAttributeEntity.setLcNodeCandidateList(attribute.getLcNodeCandidate());//设置目标节点审批人规则
                                lcAttributeEntity.setAttr(attribute.getAttr());
                            }
                            if(!StringUtil.isEmpty(lcNodeAttribute.getBpm())){
                                lcAttributeEntity.setEnd(validateEnd(lcNodeAttribute.getBpm(),rules.getTargetNodeId()));//目标节点是否为结束节点
                            }
                            LcReceiveParam lcReceiveParam = new LcReceiveParam();
                            lcReceiveParam.setTaskId(taskId);
                            lcReceiveParam.setActivityId(rules.getTargetNodeId());
                            boolean mutil = activitiUtil.validateNodeIsMultiInstance(lcReceiveParam);
                            if(mutil){
                                lcAttributeEntity.setMutil(ActivitiUtil.ACT_CODE_20);//会签
                            }else{
                                lcAttributeEntity.setMutil(ActivitiUtil.ACT_CODE_10);//非会签
                            }

                            lcAttributeEntities.add(lcAttributeEntity);//放入集合存储
                        }
                    }else{
                        LcAttributeEntity lcAttributeEntity = new LcAttributeEntity();//构造目标节点对象
                        lcAttributeEntity.setBehavior(lcNodeBtn.getLcBtn() == null ?ActivitiUtil.BEHAVIOR_10:lcNodeBtn.getLcBtn().getBehavior());
                        lcAttributeEntity.setActivityId(null);//目标节点为空
                        lcAttributeEntity.setLabel_(lcNodeBtn.getLabel_());
                        lcAttributeEntity.setNodeBtnId(lcNodeBtn.getId());//目标节点按钮id
                        lcAttributeEntity.setLcBtn(lcNodeBtn.getLcBtn());//目标节点按钮对象
                        lcAttributeEntity.setBtnAction(lcNodeBtn.getBtnAction());
                        lcAttributeEntities.add(lcAttributeEntity);//放入集合存储
//                        //判断是否需要重新从流程图中读取下一个节点
//                        commonAttribute(taskId,condition,lcAttributeEntities);//节点中按钮配置并且目标节点未配置
                    }
                }
            }
        }
        lcAttributeNEntity.setLcAttributeEntities(lcAttributeEntities);
        return new BaseResult(lcAttributeNEntity);
    }

    /**
     * 根据模块Key查询发起人所在节点及发起人所在节点的下个节点（查询最新部署）
     * @param moduleKey
     * @return
     */
    public BaseResult<LcAttributeNEntity> getLcAttributeByModuleKey(String moduleKey){
        if(StringUtil.isEmpty(moduleKey)){
            log.info("未能获取到模块Key");
            return new BaseResult("未能获取到模块key",false,null);
        }
        LcProcess lcProcess = lcProcessService.getLcProcessByModuleKey(moduleKey);
        if(null == lcProcess){
            log.info("根据模块Key条件，未能查到流程定义");
            return new BaseResult("根据模块Key条件，未能查到流程定义",false,null);
        }
        Map<String,Object> condition = new HashMap<>();
        condition.put("lcProcessId",lcProcess.getId());
        LcDeploymentHis lcDeploymentHis = lcDeploymentHisService.getLcDeploymentHisNewUnique(condition);

        if(null == lcDeploymentHis){
            log.info("未能获取到流程部署,模块Key：{}",moduleKey);
            throw new ExceptionUtil("根据模块Key未能获取到流程部署对象");
        }
        ProcessDefinition processDefinition = activitiUtil.getProcessDefinition(lcDeploymentHis.getDeploymentId());
        if(null == processDefinition){
            log.info("未能获取到流程定义,模块Key：{}",moduleKey);
            throw new ExceptionUtil("根据模块Key未能获取到流程定义");
        }
        List<UserTask> userTasks = activitiUtil.getUserTaskElements(processDefinition.getId());//查询所有用户节点
        if(CollectionUtil.isEmpty(userTasks)){
            log.info("未能获取到流程中任务节点,模块Key：{}，流程部署：{}，流程定义：{}",moduleKey,lcDeploymentHis.getDeploymentId(),processDefinition.getId());
            throw new ExceptionUtil("未能获取到流程中任务节点");
        }

        UserTask initiatorTask = null;//定义发起人节点
        LcNodeAttribute initiatorAttribute = null;//定义发起人节点扩展属性
        for(UserTask userTask: userTasks){
            String key = userTask.getId();
            String hid_ = lcDeploymentHis.getId();
            NodeAttributeParam nodeAttributeParam = new NodeAttributeParam();
            nodeAttributeParam.setHid_(hid_);
            nodeAttributeParam.setNodeId(key);
            LcNodeAttribute attribute = lcNodeAttributeService.getLcNodeAttribute(nodeAttributeParam);
            if(null == attribute){
                continue;
            }
            if(ActivitiUtil.ACT_CODE_20.equals(attribute.getInitiator())){//是第一个节点（发起人节点）
                initiatorTask = userTask;
                initiatorAttribute = attribute;
                break;
            }
        }

        if(null == initiatorTask){
            log.info("未能找到发起人节点,模块Key：{}",moduleKey);
            throw new ExceptionUtil("未能找到发起人节点");
        }
        LcAttributeNEntity lcAttributeNEntity = new LcAttributeNEntity();//当前节点临时对象
        Boolean res = activitiUtil.validateNodeIsMultiInstance(initiatorTask);
        if(res){
            lcAttributeNEntity.setMutil(ActivitiUtil.ACT_CODE_20);
        }else{
            lcAttributeNEntity.setMutil(ActivitiUtil.ACT_CODE_10);
        }
        lcAttributeNEntity.setActivityId(initiatorTask.getId());//当前节点id
        lcAttributeNEntity.setActivityName(initiatorTask.getName());//当前节点名称
        lcAttributeNEntity.setPcFormUri(initiatorAttribute.getPcFormUri());
        lcAttributeNEntity.setMobileFormUri(initiatorAttribute.getMobileFormUri());
        lcAttributeNEntity.setNodeFormFieldList(initiatorAttribute.getNodeFormField());
        lcAttributeNEntity.setAttr(initiatorAttribute.getAttr());//扩展属性
        lcAttributeNEntity.setLcNodeCandidateList(initiatorAttribute.getLcNodeCandidate());//当前节点已配置处理人
        List<LcAttributeEntity> lcAttributeEntities = new ArrayList<>();//目标节点属性集合
        List<LcNodeBtn> lcNodeBtns = initiatorAttribute.getLcNodeBtns();
        if(!CollectionUtil.isEmpty(lcNodeBtns)){//如果自定义按钮存在则
            for(LcNodeBtn lcNodeBtn: lcNodeBtns){
                List<LcJumpRules> lcJumpRules = lcNodeBtn.getLcJumpRules();
                if(!CollectionUtil.isEmpty(lcJumpRules)){
                    for(LcJumpRules rules: lcJumpRules){
                        LcAttributeEntity lcAttributeEntity = new LcAttributeEntity();//目标节点对象
                        lcAttributeEntity.setBehavior(lcNodeBtn.getLcBtn() == null ?ActivitiUtil.BEHAVIOR_10:lcNodeBtn.getLcBtn().getBehavior());
                        lcAttributeEntity.setActivityId(rules.getTargetNodeId());//目标节点id
                        lcAttributeEntity.setActivityName(rules.getNodeName());//目标节点名称
                        lcAttributeEntity.setLabel_(lcNodeBtn.getBtnLabel());
                        lcAttributeEntity.setBtnAction(lcNodeBtn.getBtnAction());
                        lcAttributeEntity.setLcBtn(lcNodeBtn.getLcBtn());//按钮对象

                        //处理目标节点办理人规则
                        NodeAttributeParam nodeAttributeParam = new NodeAttributeParam();
                        nodeAttributeParam.setHid_(initiatorAttribute.getHid_());
                        nodeAttributeParam.setNodeId(rules.getTargetNodeId());
                        LcNodeAttribute attribute = lcNodeAttributeService.getLcNodeAttribute(nodeAttributeParam);
                        if(null != attribute){
                            lcAttributeEntity.setLcNodeCandidateList(attribute.getLcNodeCandidate());//设置目标节点审批人规则
                            lcAttributeEntity.setAttr(attribute.getAttr());
                        }
                        if(!StringUtil.isEmpty(initiatorAttribute.getBpm())){
                            lcAttributeEntity.setEnd(validateEnd(initiatorAttribute.getBpm(),rules.getTargetNodeId()));
                        }

                        for(UserTask userTask: userTasks){
                            if(userTask.getId().equals(rules.getNodeId())){
                                boolean mutil = activitiUtil.validateNodeIsMultiInstance(userTask);//目标节点是否会签节点
                                if(mutil){
                                    lcAttributeEntity.setMutil(ActivitiUtil.ACT_CODE_20);//会签
                                }else{
                                    lcAttributeEntity.setMutil(ActivitiUtil.ACT_CODE_10);//非会签
                                }
                                break;
                            }
                        }
                        lcAttributeEntities.add(lcAttributeEntity);//放入集合存储
                    }
                }
            }
        }
        lcAttributeNEntity.setLcAttributeEntities(lcAttributeEntities);
        return new BaseResult(lcAttributeNEntity);
    }

    /**
     * 根据模块Key+版本号查询发起人所在节点及发起人所在节点的下个节点（查询最新部署）
     * @param moduleKey
     * @return
     */
    public BaseResult<LcAttributeNEntity> getLcAttributeByModuleKey(String moduleKey,String version){
        if(StringUtil.isEmpty(moduleKey)){
            log.info("未能获取到模块Key");
            return new BaseResult("未能获取到模块key",false,null);
        }
        LcProcess lcProcess = lcProcessService.getLcProcessByModuleKey(moduleKey);
        if(null == lcProcess){
            log.info("根据模块Key条件，未能查到流程定义");
            return new BaseResult("根据模块Key条件，未能查到流程定义",false,null);
        }
        Map<String,Object> condition = new HashMap<>();
        condition.put("lcProcessId",lcProcess.getId());
        condition.put("version",version);
        LcDeploymentHis lcDeploymentHis = lcDeploymentHisService.getLcDeploymentHisNewUnique(condition);

        if(null == lcDeploymentHis){
            log.info("未能获取到流程部署,模块Key：{}",moduleKey);
            throw new ExceptionUtil("根据模块Key未能获取到流程部署对象");
        }
        ProcessDefinition processDefinition = activitiUtil.getProcessDefinition(lcDeploymentHis.getDeploymentId());
        if(null == processDefinition){
            log.info("未能获取到流程定义,模块Key：{}",moduleKey);
            throw new ExceptionUtil("根据模块Key未能获取到流程定义");
        }
        List<UserTask> userTasks = activitiUtil.getUserTaskElements(processDefinition.getId());//查询所有用户节点
        if(CollectionUtil.isEmpty(userTasks)){
            log.info("未能获取到流程中任务节点,模块Key：{}，流程部署：{}，流程定义：{}",moduleKey,lcDeploymentHis.getDeploymentId(),processDefinition.getId());
            throw new ExceptionUtil("未能获取到流程中任务节点");
        }

        UserTask initiatorTask = null;//定义发起人节点
        LcNodeAttribute initiatorAttribute = null;//定义发起人节点扩展属性
        for(UserTask userTask: userTasks){
            String key = userTask.getId();
            String hid_ = lcDeploymentHis.getId();
            NodeAttributeParam nodeAttributeParam = new NodeAttributeParam();
            nodeAttributeParam.setHid_(hid_);
            nodeAttributeParam.setNodeId(key);
            LcNodeAttribute attribute = lcNodeAttributeService.getLcNodeAttribute(nodeAttributeParam);
            if(null == attribute){
                continue;
            }
            if(ActivitiUtil.ACT_CODE_20.equals(attribute.getInitiator())){//是第一个节点（发起人节点）
                initiatorTask = userTask;
                initiatorAttribute = attribute;
                break;
            }
        }

        if(null == initiatorTask){
            log.info("未能找到发起人节点,模块Key：{}",moduleKey);
            throw new ExceptionUtil("未能找到发起人节点");
        }
        LcAttributeNEntity lcAttributeNEntity = new LcAttributeNEntity();//当前节点临时对象
        Boolean res = activitiUtil.validateNodeIsMultiInstance(initiatorTask);
        if(res){
            lcAttributeNEntity.setMutil(ActivitiUtil.ACT_CODE_20);
        }else{
            lcAttributeNEntity.setMutil(ActivitiUtil.ACT_CODE_10);
        }
        lcAttributeNEntity.setActivityId(initiatorTask.getId());//当前节点id
        lcAttributeNEntity.setActivityName(initiatorTask.getName());//当前节点名称
        lcAttributeNEntity.setPcFormUri(initiatorAttribute.getPcFormUri());
        lcAttributeNEntity.setMobileFormUri(initiatorAttribute.getMobileFormUri());
        lcAttributeNEntity.setNodeFormFieldList(initiatorAttribute.getNodeFormField());
        lcAttributeNEntity.setAttr(initiatorAttribute.getAttr());//扩展属性
        lcAttributeNEntity.setLcNodeCandidateList(initiatorAttribute.getLcNodeCandidate());//当前节点已配置处理人
        List<LcAttributeEntity> lcAttributeEntities = new ArrayList<>();//目标节点属性集合
        List<LcNodeBtn> lcNodeBtns = initiatorAttribute.getLcNodeBtns();
        if(!CollectionUtil.isEmpty(lcNodeBtns)){//如果自定义按钮存在则
            for(LcNodeBtn lcNodeBtn: lcNodeBtns){
                List<LcJumpRules> lcJumpRules = lcNodeBtn.getLcJumpRules();
                if(!CollectionUtil.isEmpty(lcJumpRules)){
                    for(LcJumpRules rules: lcJumpRules){
                        LcAttributeEntity lcAttributeEntity = new LcAttributeEntity();//目标节点对象
                        lcAttributeEntity.setBehavior(lcNodeBtn.getLcBtn() == null ?ActivitiUtil.BEHAVIOR_10:lcNodeBtn.getLcBtn().getBehavior());
                        lcAttributeEntity.setActivityId(rules.getTargetNodeId());//目标节点id
                        lcAttributeEntity.setActivityName(rules.getNodeName());//目标节点名称
                        lcAttributeEntity.setLabel_(lcNodeBtn.getBtnLabel());
                        lcAttributeEntity.setBtnAction(lcNodeBtn.getBtnAction());
                        lcAttributeEntity.setLcBtn(lcNodeBtn.getLcBtn());//按钮对象

                        //处理目标节点办理人规则
                        NodeAttributeParam nodeAttributeParam = new NodeAttributeParam();
                        nodeAttributeParam.setHid_(initiatorAttribute.getHid_());
                        nodeAttributeParam.setNodeId(rules.getTargetNodeId());
                        LcNodeAttribute attribute = lcNodeAttributeService.getLcNodeAttribute(nodeAttributeParam);
                        if(null != attribute){
                            lcAttributeEntity.setLcNodeCandidateList(attribute.getLcNodeCandidate());//设置目标节点审批人规则
                            lcAttributeEntity.setAttr(attribute.getAttr());
                        }
                        if(!StringUtil.isEmpty(initiatorAttribute.getBpm())){
                            lcAttributeEntity.setEnd(validateEnd(initiatorAttribute.getBpm(),rules.getTargetNodeId()));
                        }

                        for(UserTask userTask: userTasks){
                            if(userTask.getId().equals(rules.getNodeId())){
                                boolean mutil = activitiUtil.validateNodeIsMultiInstance(userTask);//目标节点是否会签节点
                                if(mutil){
                                    lcAttributeEntity.setMutil(ActivitiUtil.ACT_CODE_20);//会签
                                }else{
                                    lcAttributeEntity.setMutil(ActivitiUtil.ACT_CODE_10);//非会签
                                }
                                break;
                            }
                        }
                        lcAttributeEntities.add(lcAttributeEntity);//放入集合存储
                    }
                }
            }
        }
        lcAttributeNEntity.setLcAttributeEntities(lcAttributeEntities);
        return new BaseResult(lcAttributeNEntity);
    }
    ///////////////////////////////////以下为本接口中方法调用/////////////////////////

    /**
     * 根据当前任务节点查找当前节点属性
     * @param taskId
     * @return
     */
    private LcNodeAttribute getLcNodeAttributeByTaskId(String taskId){
        String deploymentId = activitiUtil.getDeploymentIdByTaskId(taskId);
        HistoricTaskInstance historicTaskInstance = activitiUtil.getTaskById(taskId);
        LcNodeAttribute lcNodeAttribute = null;
        if(!StringUtil.isEmpty(deploymentId) && null != historicTaskInstance){
            LcDeploymentHis lcDeploymentHis = lcDeploymentHisService.getLcDeploymentHisByDeploymentId(deploymentId);
            if(null != lcDeploymentHis){
                NodeAttributeParam nodeAttributeParam = new NodeAttributeParam();
                nodeAttributeParam.setHid_(lcDeploymentHis.getId());
                nodeAttributeParam.setNodeId(historicTaskInstance.getTaskDefinitionKey());
                lcNodeAttribute = lcNodeAttributeService.getLcNodeAttribute(nodeAttributeParam);
            }
            if(null != lcNodeAttribute){
                lcNodeAttribute.setBpm(lcDeploymentHis.getBpmn());
            }
        }
        return lcNodeAttribute;
    }

    /**
     * 查找节点审批人
     * @param historicTaskInstance
     * @param multiInstance
     * @param activityImplId
     * @return
     */
    private String getMutilValue(HistoricTaskInstance historicTaskInstance,boolean multiInstance,String activityImplId){
        String mutilValue = null;
        if(multiInstance){//会签节点 则从历史集合中拿
            LcHisMutil lcHisMutil = new LcHisMutil();
            lcHisMutil.setActivityId(activityImplId);
            lcHisMutil.setProInstId(historicTaskInstance.getProcessInstanceId());
            List<LcHisMutil> lcHisMutils = getLcHisMutil(lcHisMutil);
            if(!CollectionUtil.isEmpty(lcHisMutils)){
                for(LcHisMutil hisMutil: lcHisMutils){
                    if(StringUtil.isEmpty(mutilValue)){
                        mutilValue = hisMutil.getAssignee();
                    }else{
                        mutilValue = mutilValue+","+hisMutil.getAssignee();
                    }
                }
            }
        }else{
            mutilValue = historicTaskInstance.getAssignee();
        }
        return mutilValue;
    }

    /**
     * 查找当前会签节点最后一次的点击同意的目标节点审批人(会签最后点击驳回动作但反向动作为同意 此时需要带出最新一个同意的目标节点审批人集合)
     * @param lcReceiveNParam 参数
     * @param historicTaskInstance 任务实例
     * @param multiInstance 是否会签
     * @param activityImplId 当前会签节点id
     * @return
     */
    private void getTargetMutilValue(LcReceiveNParam lcReceiveNParam,HistoricTaskInstance historicTaskInstance,boolean multiInstance,String activityImplId){
        String mutilValue = null;
        if(multiInstance){//会签节点 则从历史集合中拿
            Map<String,Object> map = new HashMap<>();
            map.put("procInstId",historicTaskInstance.getProcessInstanceId());
            map.put("activityId",activityImplId);
            map.put("action_",10);
            LcSignRecord lcSignRecord = lcSignRecordService.getLcSignRecordSingle(map);
            if(null != lcSignRecord){
                mutilValue = lcSignRecord.getMutilValue();
            }
        }
        if(StringUtil.isEmpty(mutilValue)){
            log.info("会签节点方向结果时,未能获取到下个节点经办人,{}",lcReceiveNParam);
            throw new ExceptionUtil("会签节点方向结果时,未能获取到下个节点经办人");
        }
        List<LcReceiveParam> lcReceiveParams = new ArrayList<>();
        LcReceiveParam lcReceiveParam = new LcReceiveParam();
        lcReceiveParam.setMutilValue(mutilValue);//构造最后一个审批人点击同意后的下一个节点审批人
        lcReceiveParam.setActivityId(lcReceiveNParam.getActivityId());//目标节点id
        lcReceiveParam.setNeedHandledTransactor(true);
        lcReceiveParams.add(lcReceiveParam);
        lcReceiveNParam.setLcReceiveParams(lcReceiveParams);
    }

    /**
     * 查找历史节点最新审批人
     * @param lcReceiveNParam
     * @param historicTaskInstance
     * @param multiInstance
     * @return
     */
    private Map<String,Object> getOldMutilValue(LcReceiveNParam lcReceiveNParam,HistoricTaskInstance historicTaskInstance,boolean multiInstance){
        Map<String,Object> map = lcReceiveNParam.getVariables();
        Map<String,Object> mutilValueMap = new HashMap<>();//审批人
        String mutilValue = null;
        lcReceiveNParam.setProcessInstanceId(historicTaskInstance.getProcessInstanceId());
        List<HistoricActivityInstance> hisAcitivitis = activitiUtil.getHisAcitivitis(lcReceiveNParam);//需要过滤最近一次是否为会签节点（如果会签节点，则还需要将变量动态设置进去，待实现）
        if(!CollectionUtil.isEmpty(hisAcitivitis)){
            HistoricActivityInstance historicActivityInstance = hisAcitivitis.get(0);
            if(null != historicActivityInstance){
                ActivityImpl activityImpl = activitiUtil.findActivitiImpl(lcReceiveNParam.getTaskId(),lcReceiveNParam.getActivityId());
                if(multiInstance){//会签节点
                    //原节点如果是会签节点则调出最大批次的审批人
                    TaskDefinition taskDefinition = null;
                    if(((ActivityImpl) activityImpl).getActivityBehavior() instanceof SequentialMultiInstanceBehavior){//会签多实例串行
                        SequentialMultiInstanceBehavior sequentialMultiInstanceBehavior = ((SequentialMultiInstanceBehavior) ((ActivityImpl) activityImpl).getActivityBehavior());
                        taskDefinition = ((UserTaskActivityBehavior)sequentialMultiInstanceBehavior.getInnerActivityBehavior()).getTaskDefinition();
                    }else if(((ActivityImpl) activityImpl).getActivityBehavior() instanceof ParallelMultiInstanceBehavior){//会签多实例并行
                        ParallelMultiInstanceBehavior parallelMultiInstanceBehavior =  ((ParallelMultiInstanceBehavior) ((ActivityImpl) activityImpl).getActivityBehavior());
                        taskDefinition = ((UserTaskActivityBehavior)parallelMultiInstanceBehavior.getInnerActivityBehavior()).getTaskDefinition();
                    }else if(((ActivityImpl) activityImpl).getActivityBehavior() instanceof MultiInstanceActivityBehavior){
                        MultiInstanceActivityBehavior multiInstanceActivityBehavior =  ((MultiInstanceActivityBehavior) ((ActivityImpl) activityImpl).getActivityBehavior());
                        taskDefinition = ((UserTaskActivityBehavior)multiInstanceActivityBehavior.getInnerActivityBehavior()).getTaskDefinition();
                    }
                    String expression = null;
                    if(null != taskDefinition && null != taskDefinition.getAssigneeExpression()){//如果会签节点中没有办理人变量没有设置 则标记为需要重新动态分配
                        expression = taskDefinition.getAssigneeExpression().getExpressionText().replace("${","").replace("}","");
                    }else{
                        String deploymentId = activitiUtil.getDeploymentIdByTaskId(lcReceiveNParam.getTaskId());//根据当前任务id查找部署编号
                        LcDeploymentHis lcDeploymentHis = lcDeploymentHisService.getLcDeploymentHisByDeploymentId(deploymentId);
                        NodeAttributeParam nodeAttributeParam = new NodeAttributeParam();
                        nodeAttributeParam.setHid_(lcDeploymentHis.getId());
                        nodeAttributeParam.setNodeId(lcReceiveNParam.getActivityId());
                        LcNodeAttribute lcNodeAttributeTarget = lcNodeAttributeService.getLcNodeAttribute(nodeAttributeParam);
                        expression = lcNodeAttributeTarget.getMutilKey();
                    }
                    if(CollectionUtil.isEmpty(map)){
                        map = new HashMap<>();
                    }
                    LcHisMutil lcHisMutil = new LcHisMutil();
                    lcHisMutil.setActivityId(lcReceiveNParam.getActivityId());
                    lcHisMutil.setProInstId(historicActivityInstance.getProcessInstanceId());
                    List<LcHisMutil> lcHisMutils = getLcHisMutil(lcHisMutil);
                    if(!CollectionUtil.isEmpty(lcHisMutils)){
                        for(LcHisMutil hisMutil: lcHisMutils){
                            if(StringUtil.isEmpty(mutilValue)){
                                mutilValue = hisMutil.getAssignee();
                            }else{
                                mutilValue = mutilValue+","+hisMutil.getAssignee();
                            }
                        }
                    }
                    if(StringUtil.isEmpty(mutilValue)){
                        throw new ExceptionUtil("驳回到原会签节点时，未能获取到原审批人");
                    }
                    map.put(expression, Arrays.asList(mutilValue.split(",")));//传递变量值 会签节点从历史记录中拿
                    lcReceiveNParam.setVariables(map);//设置变量
                    List<LcReceiveParam> lcReceiveParams = lcReceiveNParam.getLcReceiveParams();
                    if(!CollectionUtil.isEmpty(lcReceiveParams)){
                        for(LcReceiveParam lcReceiveParam:lcReceiveParams){
                            lcReceiveParam.setNeedHandledTransactor(true);
                            lcReceiveParam.setMutilValue(mutilValue);//设置人员
                        }
                    }else{
                        lcReceiveParams = new ArrayList<>();
                        LcReceiveParam lcReceiveParam = new LcReceiveParam();
                        lcReceiveParam.setActivityId(lcReceiveNParam.getActivityId());
                        lcReceiveParam.setMutilValue(mutilValue);
                        lcReceiveParam.setNeedHandledTransactor(true);
                        lcReceiveParams.add(lcReceiveParam);
                    }
                    lcReceiveNParam.setLcReceiveParams(lcReceiveParams);
                    lcReceiveNParam.setMutilValue(mutilValue);
                    validateCanBatchLcHisMutil(Arrays.asList(mutilValue.split(",")), historicTaskInstance,activityImpl);//验证是否需要完成会签结果并创建下个节点会签人
                }else{//普通节点 从原节点拿即可
                    mutilValue = hisAcitivitis.get(0).getAssignee();
                }
            }else{
                throw new ExceptionUtil("驳回到原会签节点时，historicActivityInstance is null");
            }
        }else{
            throw new ExceptionUtil("驳回到原会签节点时，hisAcitivitis is null");
        }
        mutilValueMap.put("mutilValue",mutilValue);
        return mutilValueMap;
    }

    /**
     * 批量新增会签节点历史人员
     * @param assigneeList
     * @param processInstanceId
     * @param activityImpl
     */
    private void addBatchLcHisMutil(List<String> assigneeList,String processInstanceId,ActivityImpl activityImpl){
        LcHisMutil lcHisMutilPar = new LcHisMutil();
        lcHisMutilPar.setActivityId(activityImpl.getId());
        lcHisMutilPar.setProInstId(processInstanceId);
        Integer batch = lcHisMutilService.getMaxBatch(lcHisMutilPar);
        if(null == batch){
            batch = 0;
        }else{
            batch += 1;
        }
        List<LcHisMutil> lcHisMutils = new ArrayList<>();
        for(String str: assigneeList){
            LcHisMutil lcHisMutil = new LcHisMutil();
            lcHisMutil.setAssignee(str);//设置审批人编号
            lcHisMutil.setExecuteId(null);//实在执行实例id
            lcHisMutil.setId(toUUID());//设置主键
            lcHisMutil.setProInstId(processInstanceId);//设置流程实例id
            lcHisMutil.setActivityId(activityImpl.getId());//设置会签节点id（目标节点）
            lcHisMutil.setCreateTime(getDate());//创建时间
            lcHisMutil.setCreateId(getXtUid());//创建人
            lcHisMutil.setBatch(batch);
            if(null != activityImpl.getProperty("name")){
                lcHisMutil.setActivityName(String.valueOf(activityImpl.getProperty("name")));//设置节点名称
            }
            lcHisMutils.add(lcHisMutil);
        }
        lcHisMutilService.addBatchLcHisMutil(lcHisMutils);

        addSign(batch,assigneeList,processInstanceId,activityImpl);
    }

    /**
     * 批量新增会签节
     * @param batch
     * @param assigneeList
     * @param processInstanceId
     * @param activityImpl
     */
    private void addSign(Integer batch,List<String> assigneeList,String processInstanceId,ActivityImpl activityImpl){
        LcSign lcSign = new LcSign();
        lcSign.setNrOfCompletedInstances(0);
        lcSign.setNrOfInstances(assigneeList.size());
        if(null != activityImpl.getProcessDefinition()){
            lcSign.setProcDefId(activityImpl.getProcessDefinition().getId());
        }
        lcSign.setExecutionId(null);
        if(null != activityImpl.getProperty("name")){
            lcSign.setName(String.valueOf(activityImpl.getProperty("name")));//设置节点名称
        }
        lcSign.setBatch(batch);
        lcSign.setTaskDefKey(activityImpl.getId());
        lcSign.setProcInstId(processInstanceId);
//        List<LcSignRecord> lcSignRecordList = new ArrayList<>();
//        for(String str: assigneeList){
//            LcSignRecord lcSignRecord = new LcSignRecord();
//            lcSignRecord.setUser_id(str);//设置审批人编号
//            lcSignRecord.setTask_id(null);
//            lcSignRecord.setBatch(batch);
//            lcSignRecordList.add(lcSignRecord);
//        }
//        lcSign.setLcSignRecords(lcSignRecordList);
        lcSignService.addLcSign(lcSign);
    }

    /**
     * 查找节点属性
     * @param deploymentId
     * @param activitiImplId
     * @return
     */
    private LcNodeAttribute getNodeAttribute(String deploymentId,String activitiImplId){
        NodeAttributeParam nodeAttributeParam = new NodeAttributeParam();
        //获取当前任务所在节点扩展属性
        LcDeploymentHis lcDeploymentHis = lcDeploymentHisService.getLcDeploymentHisByDeploymentId(deploymentId);
        nodeAttributeParam.setHid_(lcDeploymentHis.getId());
        nodeAttributeParam.setNodeId(activitiImplId);
        LcNodeAttribute lcNodeAttribute = lcNodeAttributeService.getLcNodeAttribute(nodeAttributeParam);
        if(null != lcNodeAttribute){
            lcNodeAttribute.setBpm(lcDeploymentHis.getBpmn());
        }
        return lcNodeAttribute;
    }

    /**
     * 查询历史会签人员
     * @param lcHisMutil
     * @return
     */
    private List<LcHisMutil> getLcHisMutil(LcHisMutil lcHisMutil){
        if(StringUtil.isEmpty(lcHisMutil.getActivityId())){
            return new ArrayList<>();
        }
        if(StringUtil.isEmpty(lcHisMutil.getProInstId())){
            return new ArrayList<>();
        }
        Integer batch = lcHisMutilService.getMaxBatch(lcHisMutil);
        if(null == batch){
            lcHisMutil.setBatch(0);//始终使用最新一批次
        }else{
            lcHisMutil.setBatch(batch);//始终使用最新一批次
        }
        List<LcHisMutil> lcHisMutils = lcHisMutilService.getLcHisMutilListByCondition(lcHisMutil);
        return lcHisMutils;
    }

    /**
     *
     * @param lcHisMutils
     * @return
     */
    private Map<String,String> doLcHisMutil(List<LcHisMutil> lcHisMutils){
        Map<String,String> map = new HashMap<>();
        if(!CollectionUtil.isEmpty(lcHisMutils)){
            for(LcHisMutil lcHisMutil: lcHisMutils){
                map.put(lcHisMutil.getAssignee(),lcHisMutil.getAssignee());
            }
        }
        return map;
    }

    /**
     *
     * @param lcHisMutil
     * @return
     */
    private List<String> commonMutil(LcHisMutil lcHisMutil){
        List<String> list = new ArrayList<>();
        List<LcHisMutil> lcHisMutils = getLcHisMutil(lcHisMutil);
        Map<String,String> map = doLcHisMutil(lcHisMutils);
        if(!CollectionUtil.isEmpty(map)){
            Iterator<Map.Entry< String, String >> iterator = map.entrySet().iterator();
            while (iterator.hasNext()) {
                Map.Entry< String, String > entry = iterator.next();
                list.add(entry.getKey());
            }
        }
        return list;
    }

    /**
     * 查找发起人
     * @return
     */
    private LcNodeAttribute getLcNodeAttributeInitiator(String hid_){
        if(StringUtil.isEmpty(hid_)){
            return null;
        }else{
            Map<String,Object> condition = new HashMap<>();
            condition.put("hid_",hid_);
            condition.put("initiator",ActivitiUtil.ACT_CODE_20);
            List<LcNodeAttribute> ls =lcNodeAttributeService.getLcNodeAttributeListByCondition(condition);

            if(CollectionUtil.isEmpty(ls)){
                return null;
            }

            if(ls.size()>1){
                throw new ExceptionUtil("找到多个发起人");
            }
            return ls.get(0);
        }
    }

    /**
     * 处理审批人
     * @param lcReceiveParam
     * @return
     */
    private String doLcReceiveParam(LcReceiveParam lcReceiveParam){
        String mutilValue = null;
        StringBuilder stringBuilder = new StringBuilder();
        if(!StringUtil.isEmpty(lcReceiveParam.getMutilValue())){//处理办理人单个
            String [] mutilValues = lcReceiveParam.getMutilValue().split(",");
            mutilValue = mutilValues[0];//取出第一个
            if(null != mutilValues){
                for(int i = 0; i < mutilValues.length; i++){
                    if(i==0){
                        continue;
                    }
                    if(null == stringBuilder || StringUtil.isEmpty(stringBuilder.toString())){
                        stringBuilder.append(mutilValues[i]);
                    }else{
                        stringBuilder.append(","+mutilValues[i]);
                    }
                }
                lcReceiveParam.setMutilValue(stringBuilder.toString());//重置最新记录
            }
        }
        return mutilValue;
    }

    /**
     *
     * @param lcReceiveNParam
     * @param lcNodeAttribute
     */
    private Map<String,Object> computeMutil(LcReceiveNParam lcReceiveNParam,LcNodeAttribute lcNodeAttribute){
        Map<String,Object> map = new HashMap<>();
        boolean result = false;
        String behavior = lcReceiveNParam.getBehavior();
        LcReceiveParam lcReceiveParam =  new LcReceiveParam();
        lcReceiveParam.setTaskId(lcReceiveNParam.getTaskId());
        boolean mutil = activitiUtil.validateNodeIsMultiInstance(lcReceiveParam);
        if(null != lcNodeAttribute && !StringUtil.isEmpty(lcNodeAttribute.getSupportFreeJump())){
            lcReceiveNParam.setComplete(lcNodeAttribute.getSupportFreeJump());//设置完成动作向下个节点流转采用模式
        }
        if(mutil){//如果当前任务为会签节点则处理会签业务
            map.put("multilInstance",true);
            List<Task> taskList = activitiUtil.getTaskList(lcReceiveNParam.getTaskId());
            if(!CollectionUtil.isEmpty(taskList)){
                Map<String,Object> condition = new HashMap<>();
                condition.put("taskDefKey",taskList.get(0).getTaskDefinitionKey());//解决指定节点下批次问题
                condition.put("procInstId",taskList.get(0).getProcessInstanceId());
                Integer batch = lcSignService.getMaxBatch(condition);
                condition.put("batch",batch);
                List<LcSign> lcSignList = lcSignService.getLcSignListByCondition(condition);
                if(!CollectionUtil.isEmpty(lcSignList)){
                    LcSign lcSign = lcSignList.get(0);
                    LcSignRecord lcSignRecord =  new LcSignRecord();
                    lcSignRecord.setAction_(behavior);
                    lcSignRecord.setId(toUUID());
                    lcSignRecord.setTaskId(lcReceiveNParam.getTaskId());
                    lcSignRecord.setBatch(batch);
                    lcSignRecord.setLcSignId(lcSign.getId());
                    lcSignRecord.setUserId(taskList.get(0).getAssignee());
                    lcSignRecord.setCreateTime(getDate());
                    lcSignRecord.setComment(lcReceiveNParam.getComment());
                    if(!CollectionUtil.isEmpty(lcReceiveNParam.getLcReceiveParams())){
                        lcSignRecord.setActivityId(lcReceiveNParam.getLcReceiveParams().get(0).getActivityId());
                        lcSignRecord.setMutilValue(lcReceiveNParam.getLcReceiveParams().get(0).getMutilValue());
                    }
                    lcSignRecordService.addLcSignRecord(lcSignRecord);
                    condition.put("lcSignId",lcSign.getId());
                    List<LcSignRecord> lcSignRecordList = lcSignRecordService.getLcSignRecordListByCondition(condition);
                    Map<String,Object> mutilMap = doMutilRule(taskList,lcReceiveNParam,lcNodeAttribute,lcSignRecordList,lcSign);
                    result = (Boolean) mutilMap.get("result");
                    map.put("actionResult",mutilMap.get("actionResult"));
                }
            }
        }else{
            map.put("multilInstance",false);
        }
        map.put("result",result);
        return map;
    }

    /**
     * 计算会签规则（仅限于会签节点的同意，驳回，弃权三个逻辑 做出结果导向，如果导向满足则动态改变目标节点）
     * @param lcReceiveNParam
     * @param lcNodeAttribute 当前任务对应的节点属性
     */
    private Map<String,Object> doMutilRule(List<Task> taskList,LcReceiveNParam lcReceiveNParam,LcNodeAttribute lcNodeAttribute,List<LcSignRecord> lcSignRecordList,LcSign lcSign){
        boolean result = false;//会签处理结果
        String actionResult = lcReceiveNParam.getBehavior();//动作执行结果（可以为反向结果，如明明点击驳回，但是最后根据规则结果可能是同意的结果）
        Map<String,Object> map = new HashMap<>();
        if(!StringUtil.isEmpty(lcReceiveNParam.getTaskId()) && null != lcNodeAttribute && !StringUtil.isEmpty(lcNodeAttribute.getPolicy())){
            int num = taskList.size();
            String policy = lcNodeAttribute.getPolicy();/**会签决策方式：10通过20驳回30弃权**/
            String votingStrategy = lcNodeAttribute.getVotingStrategy();/**投票策略:10百分比20投票数**/
            Integer percentage = null ==lcNodeAttribute.getPercentage()?100:lcNodeAttribute.getPercentage();/**百分比,如果为空则100%**/
            Integer numberVotes = null ==lcNodeAttribute.getNumberVotes()?1:lcNodeAttribute.getNumberVotes();/**投票数，如果为空则1票通过**/
            String needAllVote  = StringUtil.isEmpty(lcNodeAttribute.getNeedAllVote())?"10":lcNodeAttribute.getNeedAllVote();/**是否需要所有人员投票10是20否，默认是**/

            int nrOfInstances = lcSign.getNrOfInstances();//总票数
            int passCount = 0;//当前通过票数
            int rejectCount = 0;//当前拒绝票数
            int waiverCount = 0;//当前弃权票数
            int passWaiverCount = 0;//当前通过+弃权票数总和
            int votedCount = 0 ;//已投票总数（包含通过+拒绝+弃权）

            double passRatio = 0L;//当前通过比例
            double waiverRatio = 0L;//当前弃权比例
            double rejectRatio = 0L;//当前拒绝比例
            double passWaiverRatio = 0L;//当前通过+弃权票数 比例
            if(!CollectionUtil.isEmpty(lcSignRecordList)){
                for(LcSignRecord lcSignRecord: lcSignRecordList){
                    if(lcSignRecord.getAction_().equals(ActivitiUtil.BEHAVIOR_10)){
                        passCount++;
                    }
                    if(lcSignRecord.getAction_().equals(ActivitiUtil.BEHAVIOR_20)){
                        rejectCount++;
                    }
                    if(lcSignRecord.getAction_().equals(ActivitiUtil.BEHAVIOR_30)){
                        waiverCount++;
                    }
                }

                passWaiverCount = passCount+waiverCount;
                passRatio = (double)passCount/nrOfInstances;
                waiverRatio = (double)waiverCount/nrOfInstances;
                rejectRatio = (double)rejectCount/nrOfInstances;
                passWaiverRatio = (double)passWaiverCount/nrOfInstances;
                rejectRatio = rejectRatio * 100;
                passWaiverRatio = passWaiverRatio*100;
//                votedCount = waiverCount+rejectCount+passCount;//计算当前投票数总和
                votedCount = lcSignRecordList.size();//计算当前投票数总和 （即等于waiverCount+rejectCount+passCount）
                log.info("当前已投票总数：{}，对比通过计算已投票总数：{}",votedCount,waiverCount+rejectCount+passCount);
                if(needAllVote.equals(activitiUtil.ACT_CODE_10) && lcSignRecordList.size() < nrOfInstances){//如果需要所有人审批 并且还未达到投票结果规则（ 则判断当前已审批的数量与总数比较） 则继续等待
                    log.info("还未满足决策条件：{}-{}-{}-{}",lcReceiveNParam,lcNodeAttribute,lcSignRecordList,lcSign);
                }else{//结果算法（优先级：先行为再->决策方式->最后投票策略）
                    if(lcReceiveNParam.getBehavior().equals(activitiUtil.BEHAVIOR_10) || lcReceiveNParam.getBehavior().equals(activitiUtil.BEHAVIOR_30)){//用户行为：“通过或弃权”

                        ////////////用户行为：“通过或弃权” 开始
                        if(policy.equals(activitiUtil.ACT_CODE_10) || policy.equals(activitiUtil.ACT_CODE_30)){//决策方式启用通过或弃权类型 此时按规则处理（通过或弃权都认为是通过）
                            if(votingStrategy.equals(activitiUtil.ACT_CODE_10)){ //1.投票策略按百分比
                                if(percentage == 100){//决策方式：“通过或弃权”，用户行为：“通过或弃权”，剔除百分比为100
                                    if(rejectRatio > 0){//如果存在拒绝行为则直接反向结果
                                        log.info("决策方式：“通过或弃权”，用户行为：“通过或弃权”，当前百分比配置100%，存在拒绝票数，即一票否决制");
                                        reverseSetActivityIdByNodeBtn(lcReceiveNParam,lcNodeAttribute,ActivitiUtil.BEHAVIOR_20);
                                        setActivityIdByNodeBtn(lcReceiveNParam ,lcNodeAttribute);
                                        actionResult =  ActivitiUtil.BEHAVIOR_20;//反向结果为驳回行为
                                        result = true;
                                    }else{
                                        if(passWaiverRatio>=percentage){//通过条件满足 则获取通过规则绑定的下一个节点
                                            log.info("投票结果按百分比 通过条件满足 则获取通过规则绑定的下一个节点，即正向流转");
                                            setActivityIdByNodeBtn(lcReceiveNParam ,lcNodeAttribute);
                                            result = true;
                                        }else{
                                            log.info("决策方式：“通过或弃权”，用户行为：“通过或弃权”，剔除百分比为100场景，还未满足决策条件：{}-{}-{}-{}",lcReceiveNParam,lcNodeAttribute,lcSignRecordList,lcSign);
                                        }
                                    }
                                }else{//注意不存在一票否决制场景（）
                                    if(passWaiverRatio>=percentage){//通过条件满足 则获取通过规则绑定的下一个节点
                                        log.info("投票结果按百分比 通过条件满足 则获取通过规则绑定的下一个节点");
                                        setActivityIdByNodeBtn(lcReceiveNParam ,lcNodeAttribute);
                                        result = true;
                                    }else{//判断是否所有人都审核
                                        if(votedCount < nrOfInstances){//决策方式：“通过或弃权”，用户行为：“通过或弃权”，当前投票总数还没有达到应该投票总数，还未满足决策条件
                                            log.info("决策方式：“通过或弃权”，用户行为：“通过或弃权”，当前投票总数还没有达到应该投票总数，还未满足决策条件：{}-{}-{}-{}",lcReceiveNParam,lcNodeAttribute,lcSignRecordList,lcSign);
                                        }else{//反向结果
                                            reverseSetActivityIdByNodeBtn(lcReceiveNParam,lcNodeAttribute,ActivitiUtil.BEHAVIOR_20);
                                            setActivityIdByNodeBtn(lcReceiveNParam ,lcNodeAttribute);
                                            actionResult =  ActivitiUtil.BEHAVIOR_20;//反向结果为驳回行为
                                            result = true;
                                        }
                                    }
                                }

                            }else if(votingStrategy.equals(activitiUtil.ACT_CODE_20)){ //2.“投票策略”结果按投票数
                                if(passWaiverCount>=numberVotes){//通过条件满足 则获取通过规则绑定的下一个节点
                                    log.info("“投票策略”结果按投票数 通过条件满足 则获取通过规则绑定的下一个节点");
                                    setActivityIdByNodeBtn(lcReceiveNParam ,lcNodeAttribute);
                                    result = true;
                                }else {
                                    if(lcSignRecordList.size()<numberVotes){ //剔除已会签数小于投票设定数
                                        log.info("剔除已会签数小于投票设定数场景，还未满足决策条件：{}-{}-{}-{}",lcReceiveNParam,lcNodeAttribute,lcSignRecordList,lcSign);
                                    }else{
                                        //反向结果
                                        reverseSetActivityIdByNodeBtn(lcReceiveNParam,lcNodeAttribute,ActivitiUtil.BEHAVIOR_20);
                                        setActivityIdByNodeBtn(lcReceiveNParam ,lcNodeAttribute);
                                        actionResult =  ActivitiUtil.BEHAVIOR_20;//反向结果为驳回行为
                                        result = true;
                                    }
                                }
                            }else{
                                throw new ExceptionUtil("用户行为为通过，决策方式为通过或弃权，未能找到投票策略！");
                            }
                        }else if(policy.equals(ActivitiUtil.ACT_CODE_20)){//用户行为为通过 并且决策方式为拒绝 则采用反向动作

                            if(votingStrategy.equals(activitiUtil.ACT_CODE_10)){ //1.投票结果按百分比
                                if(rejectRatio>=percentage){//驳回条件满足 则满足驳回规则绑定的下一个节点
                                    log.info("投票结果按百分比 驳回条件满足 则满足驳回规则绑定的下一个节点");
                                    reverseSetActivityIdByNodeBtn(lcReceiveNParam,lcNodeAttribute,ActivitiUtil.BEHAVIOR_20);
                                    setActivityIdByNodeBtn(lcReceiveNParam ,lcNodeAttribute);
                                    actionResult =  ActivitiUtil.BEHAVIOR_20;//反向结果为驳回行为
                                    result = true;
                                }else{
                                    if(percentage == 100){//当前决策方式为拒绝100%,决策方式：“拒绝”，用户行为：“通过或弃权”， 那么有一个同意则为通过结果
                                        //反向结果
                                        setActivityIdByNodeBtn(lcReceiveNParam ,lcNodeAttribute);
                                        actionResult =  ActivitiUtil.BEHAVIOR_10;//反向结果为通过行为
                                        result = true;
                                        log.info("当前决策方式为拒绝100%,决策方式：“拒绝”，用户行为：“通过或弃权”， 那么有一个同意则为通过结果：{}-{}-{}-{}",lcReceiveNParam,lcNodeAttribute,lcSignRecordList,lcSign);
                                    }else{
                                        log.info("设置拒绝百分比小于100%，还未满足决策条件：{}-{}-{}-{}",lcReceiveNParam,lcNodeAttribute,lcSignRecordList,lcSign);
                                    }
                                }
                            }else if(votingStrategy.equals(activitiUtil.ACT_CODE_20)){ //2.“投票策略”结果按投票数
                                if(rejectCount>=numberVotes){//驳回条件满足 则满足驳回规则绑定的下一个节点
                                    log.info("“投票策略”结果按投票数 驳回条件满足 则满足驳回规则绑定的下一个节点");
                                    reverseSetActivityIdByNodeBtn(lcReceiveNParam,lcNodeAttribute,ActivitiUtil.BEHAVIOR_20);
                                    setActivityIdByNodeBtn(lcReceiveNParam ,lcNodeAttribute);
                                    actionResult =  ActivitiUtil.BEHAVIOR_20;//反向结果为驳回行为
                                    result = true;
                                }else{
                                    if(lcSignRecordList.size()<numberVotes){ //剔除已会签数小于投票设定数
                                        log.info("剔除已会签数小于投票设定数场景，还未满足决策条件：{}-{}-{}-{}",lcReceiveNParam,lcNodeAttribute,lcSignRecordList,lcSign);
                                    }else{
                                        setActivityIdByNodeBtn(lcReceiveNParam ,lcNodeAttribute);
                                        actionResult =  ActivitiUtil.BEHAVIOR_10;//反向结果为通过行为
                                        result = true;
                                    }
                                }
                            }else{
                                throw new ExceptionUtil("用户行为为“通过或弃权”，“决策方式”为拒绝，未能找到“投票策略”！");
                            }
                        }else{
                            throw new ExceptionUtil("用户行为为通过，未能找到“决策方式”！");
                        }
                        ////////////用户行为：“通过或弃权” 结束

                    }else if(lcReceiveNParam.getBehavior().equals(activitiUtil.BEHAVIOR_20)){//用户行为：“驳回”
                        ////////////用户行为：“驳回” 开始
                        if(policy.equals(ActivitiUtil.ACT_CODE_10) || policy.equals(ActivitiUtil.ACT_CODE_30)){//用户行为：“驳回” 并且决策方式：“通过或弃权” 则采用反向动作
                            if(votingStrategy.equals(activitiUtil.ACT_CODE_10)){ //1.“投票策略”结果按百分比
                                if(percentage == 100){//决策方式：“通过或弃权”，用户行为：“驳回”，那么有一个驳回则驳回 即一票否决制
                                    log.info("决策方式：“通过或弃权”，用户行为：“驳回”，那么有一个驳回则驳回 即一票否决制：{}-{}-{}-{}",lcReceiveNParam,lcNodeAttribute,lcSignRecordList,lcSign);
                                    //反向结果
                                    setActivityIdByNodeBtn(lcReceiveNParam ,lcNodeAttribute);
                                    actionResult =  ActivitiUtil.BEHAVIOR_20;//反向结果为驳回行为
                                    result = true;
                                }else{//非100%比例
                                    if(passWaiverRatio>=percentage){//通过条件满足 则获取通过规则绑定的下一个节点
                                        log.info("“投票策略”结果按百分比 通过条件满足 则获取通过规则绑定的下一个节点");
                                        reverseSetActivityIdByNodeBtn(lcReceiveNParam,lcNodeAttribute,ActivitiUtil.BEHAVIOR_10);
                                        setActivityIdByNodeBtn(lcReceiveNParam ,lcNodeAttribute);
                                        actionResult = ActivitiUtil.BEHAVIOR_10;//反向结果为驳回行为
                                        result = true;
                                    }else{
                                        if(votedCount < nrOfInstances){//决策方式：“驳回”，用户行为：“驳回”，当前投票总数还没有达到应该投票总数，还未满足决策条件
                                            log.info("决策方式：“通过或弃权”，用户行为：“驳回”，还未满足决策条件：{}-{}-{}-{}",lcReceiveNParam,lcNodeAttribute,lcSignRecordList,lcSign);
                                        }else {//反向结果
                                            setActivityIdByNodeBtn(lcReceiveNParam ,lcNodeAttribute);
                                            actionResult =  ActivitiUtil.BEHAVIOR_20;//反向结果为驳回行为
                                            result = true;
                                        }
                                    }
                                }
                            }else if(votingStrategy.equals(activitiUtil.ACT_CODE_20)){ //2.投票结果按投票数
                                if(passWaiverCount>=numberVotes){//通过条件满足 则获取通过规则绑定的下一个节点
                                    log.info("投票结果按投票数 通过条件满足 则获取通过规则绑定的下一个节点");
                                    reverseSetActivityIdByNodeBtn(lcReceiveNParam,lcNodeAttribute,ActivitiUtil.BEHAVIOR_10);
                                    setActivityIdByNodeBtn(lcReceiveNParam ,lcNodeAttribute);
                                    actionResult =  ActivitiUtil.BEHAVIOR_10;//反向结果为驳回行为
                                    result = true;
                                }else {
                                    if(lcSignRecordList.size()<numberVotes){ //剔除已会签数小于投票设定数
                                        log.info("剔除已会签数小于投票设定数场景，还未满足决策条件：{}-{}-{}-{}",lcReceiveNParam,lcNodeAttribute,lcSignRecordList,lcSign);
                                    }else {
                                        //反向结果
                                        setActivityIdByNodeBtn(lcReceiveNParam ,lcNodeAttribute);
                                        actionResult = ActivitiUtil.BEHAVIOR_20;//反向结果为驳回行为
                                        result = true;
                                    }
                                }
                            }else{
                                throw new ExceptionUtil("未能投票策略！");
                                /*废弃
                                log.info("驳回行为，并且当前会签节点最后一个处理人也已经点击驳回操作，并且决策方式非驳回，（反向动作），此时需要找到按钮对应的下一个节点（全票否决）");
                                setActivityIdByNodeBtn(lcReceiveNParam ,lcNodeAttribute);*/
                            }
                        }else if(policy.equals(activitiUtil.ACT_CODE_20) ){//决策方式启用 “驳回方式”
                            if(votingStrategy.equals(activitiUtil.ACT_CODE_10)){ //1.投票结果按百分比
                                if(percentage == 100){//决策方式：“驳回”，用户行为：“驳回”，剔除百分比为100
                                    if(passRatio>0){
                                        log.info("决策方式：“驳回”，用户行为：“驳回”，当前百分比配置100%，如果存在通过票数，即一票否决制，满足决策条件：{}-{}-{}-{}",lcReceiveNParam,lcNodeAttribute,lcSignRecordList,lcSign);
                                        reverseSetActivityIdByNodeBtn(lcReceiveNParam,lcNodeAttribute,ActivitiUtil.BEHAVIOR_10);
                                        setActivityIdByNodeBtn(lcReceiveNParam ,lcNodeAttribute);
                                        actionResult =  ActivitiUtil.BEHAVIOR_10;//反向结果为通过行为
                                        result = true;
                                    }else{
                                        if(rejectRatio>=percentage){//驳回条件满足 则满足驳回规则绑定的下一个节点，即正向流转
                                            log.info("投票结果按百分比 驳回条件满足 则满足驳回规则绑定的下一个节点，即正向流转");
                                            setActivityIdByNodeBtn(lcReceiveNParam ,lcNodeAttribute);
                                            result = true;
                                        }else{
                                            log.info("决策方式：“驳回”，用户行为：“驳回”，剔除百分比为100场景，还未满足决策条件：{}-{}-{}-{}",lcReceiveNParam,lcNodeAttribute,lcSignRecordList,lcSign);
                                        }
                                    }
                                }else{//非100%比例
                                    if(rejectRatio>=percentage){//驳回条件满足 则满足驳回规则绑定的下一个节点
                                        log.info("投票结果按百分比 驳回条件满足 则满足驳回规则绑定的下一个节点");
                                        setActivityIdByNodeBtn(lcReceiveNParam ,lcNodeAttribute);
                                        result = true;
                                    }else{
                                        if(votedCount < nrOfInstances){//决策方式：“驳回”，用户行为：“驳回”，当前投票总数还没有达到应该投票总数，还未满足决策条件
                                            log.info("决策方式：“驳回”，用户行为：“驳回”，当前投票总数还没有达到应该投票总数，还未满足决策条件：{}-{}-{}-{}",lcReceiveNParam,lcNodeAttribute,lcSignRecordList,lcSign);
                                        }else{//反向结果
                                            log.info("决策方式：“驳回”，用户行为：“驳回”，满足决策条件：{}-{}-{}-{}",lcReceiveNParam,lcNodeAttribute,lcSignRecordList,lcSign);
                                            reverseSetActivityIdByNodeBtn(lcReceiveNParam,lcNodeAttribute,ActivitiUtil.BEHAVIOR_10);
                                            setActivityIdByNodeBtn(lcReceiveNParam ,lcNodeAttribute);
                                            actionResult =  ActivitiUtil.BEHAVIOR_10;//反向结果为通过行为
                                            result = true;
                                        }
                                    }
                                }

                            }else if(votingStrategy.equals(activitiUtil.ACT_CODE_20)){ //2.投票结果按投票数
                                if(rejectCount>=numberVotes){//驳回条件满足 则满足驳回规则绑定的下一个节点
                                    log.info("投票结果按投票数 驳回条件满足 则满足驳回规则绑定的下一个节点");
                                    setActivityIdByNodeBtn(lcReceiveNParam ,lcNodeAttribute);
                                    result = true;
                                }else{
                                    if(lcSignRecordList.size()<numberVotes){ //剔除已会签数小于投票设定数
                                        log.info("剔除已会签数小于投票设定数场景，还未满足决策条件：{}-{}-{}-{}",lcReceiveNParam,lcNodeAttribute,lcSignRecordList,lcSign);
                                    }else{//反向结果
                                        reverseSetActivityIdByNodeBtn(lcReceiveNParam,lcNodeAttribute,ActivitiUtil.BEHAVIOR_10);
                                        setActivityIdByNodeBtn(lcReceiveNParam ,lcNodeAttribute);
                                        actionResult =  ActivitiUtil.BEHAVIOR_10;//反向结果为通过行为
                                        result = true;
                                    }
                                }
                            }else{
                                throw new ExceptionUtil("未能找到投票策略！");
                            }
                        }else{
                            throw new ExceptionUtil("未能决策方式！");
                        }
                    }else{//未能找到用户行为
                        throw new ExceptionUtil("未能找到用户行为！");
                        /*废弃
                        log.info("通过行为，并且当前会签节点最后一个处理人也已经点击驳回操作，并且决策方式非驳回，（反向动作），此时需要找到按钮对应的下一个节点（全票否决）");
                        setActivityIdByNodeBtn(lcReceiveNParam ,lcNodeAttribute);*/
                    }
                }
            }
        }
        map.put("result",result);//处理结果
        map.put("actionResult",actionResult);
        return map;
    }

    /**
     * 动态设置按钮动作后继续的下一个节点
     * @param lcReceiveNParam
     * @param lcNodeAttribute
     */
    private void setActivityIdByNodeBtn(LcReceiveNParam lcReceiveNParam ,LcNodeAttribute lcNodeAttribute){
        boolean findNext = false;
        if(null != lcReceiveNParam && StringUtil.isEmpty(lcReceiveNParam.getNodeBtnId())){
            List<LcReceiveParam> lcReceiveParams = lcReceiveNParam.getLcReceiveParams();
            if(!CollectionUtil.isEmpty(lcReceiveParams)){
                for(LcReceiveParam lcReceiveParam :lcReceiveParams){
                    if(StringUtil.isEmpty(lcReceiveParam.getActivityId())){
                        lcReceiveNParam.setNodeBtnId(lcReceiveParam.getNodeBtnId());
                    }else{
                        lcReceiveNParam.setActivityId(lcReceiveParam.getActivityId());
                    }
                    break;
                }
            }
        }
        if(StringUtil.isEmpty(lcReceiveNParam.getActivityId()) && null != lcNodeAttribute){
            List<LcNodeBtn> lcNodeBtns = lcNodeAttribute.getLcNodeBtns();
            if(!CollectionUtil.isEmpty(lcNodeBtns) && !StringUtil.isEmpty(lcReceiveNParam.getNodeBtnId())){
                for(LcNodeBtn lcNodeBtn: lcNodeBtns){
                    List<LcJumpRules> lcJumpRules = lcNodeBtn.getLcJumpRules();
                    if(!StringUtil.isEmpty(lcReceiveNParam.getNodeBtnId()) && StringUtil.isEmpty(lcReceiveNParam.getNodeBtnCondition())){//自定义条件为空 并且 按钮id存在
                        if(lcNodeBtn.getId().equals(lcReceiveNParam.getNodeBtnId()) && !CollectionUtil.isEmpty(lcJumpRules)){//找到当前节点点击按钮动作后对应的节点
                            for(LcJumpRules rules: lcJumpRules){
                                if(!StringUtil.isEmpty(rules.getTargetNodeId())){
                                    lcReceiveNParam.setActivityId(rules.getTargetNodeId());//设置目标节点
                                    findNext = true;
                                    break;
                                }
                            }
                        }
                    }else{//并且根据条件+按钮id查找目标节点
                        if(lcNodeBtn.getId().equals(lcReceiveNParam.getNodeBtnId()) && !CollectionUtil.isEmpty(lcJumpRules)){//找到当前节点点击按钮动作后对应的节点
                            for(LcJumpRules rules: lcJumpRules){
                                if(!StringUtil.isEmpty(rules.getTargetNodeId()) && rules.getConditions_().equals(lcReceiveNParam.getNodeBtnCondition())){
                                    lcReceiveNParam.setActivityId(rules.getTargetNodeId());//设置目标节点
                                    findNext = true;
                                    break;
                                }
                            }
                        }
                    }
                }
            }

            if(findNext ==  false){//如果还是没找到规则 则 按照流程图查找下一个节点（不在此处处理，在同意或驳回地方操作）

            }
        }
    }

    /**
     * 动态反向设置当前节点的按钮编号用于重置目标节点id
     * @param lcReceiveNParam
     * @param lcNodeAttribute
     */
    private void reverseSetActivityIdByNodeBtn(LcReceiveNParam lcReceiveNParam,LcNodeAttribute lcNodeAttribute,String behavior){
        if(StringUtil.isEmpty(lcReceiveNParam.getActivityId())){
            List<LcNodeBtn> lcNodeBtns = lcNodeAttribute.getLcNodeBtns();
            if(!CollectionUtil.isEmpty(lcNodeBtns)){
                for(LcNodeBtn lcNodeBtn: lcNodeBtns){
                    if(null != lcNodeBtn.getLcBtn() && lcNodeBtn.getLcBtn().getBehavior().equals(behavior)){//重置当前节点
                        lcReceiveNParam.setNodeBtnId(lcNodeBtn.getId());
                        break;
                    }
                }
            }
        }
    }

    /**
     * 设置行为对应节点
     * @param lcReceiveNParam
     * @param lcNodeAttribute
     */
    private void setActivityId(LcReceiveNParam lcReceiveNParam,LcNodeAttribute lcNodeAttribute,String behavior){
        lcReceiveNParam.setActivityId(null);
        if(null != lcNodeAttribute) {
            List<LcNodeBtn> lcNodeBtns = lcNodeAttribute.getLcNodeBtns();
            if(!CollectionUtil.isEmpty(lcNodeBtns)){//如果自定义按钮存在则
                for(LcNodeBtn lcNodeBtn: lcNodeBtns){
                    List<LcJumpRules> lcJumpRules = lcNodeBtn.getLcJumpRules();
                    if(!CollectionUtil.isEmpty(lcJumpRules)){
                        for(LcJumpRules rules: lcJumpRules){
                            if(null != lcNodeBtn.getLcBtn()){
                                if(behavior.equals(lcNodeBtn.getLcBtn().getBehavior())){
                                    lcReceiveNParam.setActivityId(rules.getTargetNodeId());
                                    break;
                                }
                            }
                        }
                    }
                }
            }
        }

        List<LcReceiveParam> lcReceiveParams = lcReceiveNParam.getLcReceiveParams();
        if(!CollectionUtil.isEmpty(lcReceiveParams)){
            for(int i = 0; i < lcReceiveParams.size(); i++){
                lcReceiveParams.get(i).setActivityId(lcReceiveNParam.getActivityId());
                lcReceiveParams.get(i).setMutilValue(null);
                lcReceiveParams.get(i).setNeedHandledTransactor(true);
            }
            lcReceiveNParam.setLcReceiveParams(lcReceiveParams);
        }
    }

    /**
     * 设置处理人
     * @param lcReceiveNParam
     */
    private void setAssignee(HistoricTaskInstance historicTaskInstance,LcReceiveNParam lcReceiveNParam){
        if( null != historicTaskInstance){
            List<LcReceiveParam> lcReceiveParamList = lcReceiveNParam.getLcReceiveParams();
            List<Task> tasks = activitiUtil.findTaskListByInstanceId(historicTaskInstance.getProcessInstanceId());
            if(!CollectionUtil.isEmpty(tasks)){
                for(int i = 0; i < tasks.size(); i++){
                    Task task = tasks.get(i);
                    String nodeId = task.getTaskDefinitionKey();//节点编号
                    //重新指定人
                    if(!CollectionUtil.isEmpty(lcReceiveNParam.getLcReceiveParams())){
                        for(LcReceiveParam lcReceiveParam :lcReceiveParamList){
                            if(lcReceiveParam.getNeedHandledTransactor() && nodeId.equals(lcReceiveParam.getActivityId())){//判断是否需要重新设置值
                                if(!StringUtil.isEmpty(lcReceiveParam.getMutilValue())){//处理办理人单个
                                    List<String> mutilValueList = Arrays.asList(lcReceiveParam.getMutilValue().split(","));
                                    if(! CollectionUtil.isEmpty(mutilValueList)){
                                        for(int j =0; j < mutilValueList.size();j++){
                                            if(i == j){
                                                activitiUtil.setAssignee(task.getId(),mutilValueList.get(j));
                                                break;
                                            }

                                        }
                                    }
                                }
                                if(!StringUtil.isEmpty(lcReceiveParam.getCandidates())){//处理候选人

                                }
                                if(StringUtil.isEmpty(lcReceiveParam.getCandidateGroup())){//处理组

                                }
                                continue;
                            }
                        }
                    }
                }
            }
        }
    }

    /**
     * 持久化审批记录
     * @param historicTaskInstance
     * @param lcReceiveNParam
     */
    private void persistenceAppro(HistoricTaskInstance historicTaskInstance,LcReceiveNParam lcReceiveNParam){
        LcApproval lcApproval = new LcApproval();
        lcApproval.setBehavior(lcReceiveNParam.getBehavior());
        lcApproval.setBehaviorText(lcReceiveNParam.getBehaviorText());
        lcApproval.setComment(lcReceiveNParam.getComment());
        lcApproval.setTaskDefKey(historicTaskInstance.getTaskDefinitionKey());
        lcApproval.setProcDefId(historicTaskInstance.getProcessDefinitionId());
        lcApproval.setProcInstId(historicTaskInstance.getProcessInstanceId());
        lcApproval.setTaskId(historicTaskInstance.getId());
        lcApproval.setTaskName(historicTaskInstance.getName());
        lcApproval.setUserId(historicTaskInstance.getAssignee());
        HistoricProcessInstance historicProcessInstance = activitiUtil.getHistoryProcessInstance(historicTaskInstance.getProcessInstanceId());
        if(null != historicProcessInstance){
            lcApproval.setBusinessKey(historicProcessInstance.getBusinessKey());
        }
        lcApprovalService.addLcApproval(lcApproval);
    }

    /**
     * 更新历史任务
     * @param lcMutilEntity
     */
    private void updateActHiTaskInst(LcMutilEntity lcMutilEntity){
        if(null != lcMutilEntity){
            ActHiTaskinst actHiTaskinst = new ActHiTaskinst();
            TaskEntity taskEntity = lcMutilEntity.getTaskEntity();
            if(null != taskEntity){
                actHiTaskinst.setId(taskEntity.getId());
                actHiTaskinst.setExecutionId(taskEntity.getExecutionId());
                actHiTaskinst.setProcDefId(taskEntity.getProcessDefinitionId());
                actHiTaskinst.setProcInstId(taskEntity.getProcessInstanceId());
                actHiTaskinstService.updateActHiTaskInst(actHiTaskinst);
            }
        }
    }

    /**
     * 处理第一个节点
     * @param task
     */
    private void doStartCompleteTask(Task task,LcHisParam lcHisParam){
        LcReceiveNParam lcReceiveNParam = new LcReceiveNParam();
        lcReceiveNParam.setTaskId(task.getId());
        lcReceiveNParam.setBehavior(activitiUtil.BEHAVIOR_0);//默认提交
        List<LcReceiveParam> lcReceiveParams = new ArrayList<>();
        LcReceiveParam lcReceiveParam = new LcReceiveParam();
        lcReceiveParam.setMutilValue(lcHisParam.getNextMutilValue());
        lcReceiveParams.add(lcReceiveParam);
        lcReceiveNParam.setLcReceiveParams(lcReceiveParams);
        completeTask(lcReceiveNParam);
    }

    /**
     * 封装通用当前节点及目标节点属性
     * @param taskId
     * @param condition
     * @param lcAttributeEntities
     */
    private void commonAttribute(String taskId,Map<String,Object> condition,List<LcAttributeEntity> lcAttributeEntities){
        List<TaskDefinition> taskDefinitions = activitiUtil.getNextTaskDefinitionList(taskId,condition);
        if(!CollectionUtil.isEmpty(taskDefinitions)){
            for(TaskDefinition taskDefinition: taskDefinitions){
                LcAttributeEntity lcAttributeEntity = new LcAttributeEntity();//目标节点对象
                lcAttributeEntity.setBehavior(ActivitiUtil.BEHAVIOR_10);//行为，缺省 为同意
                lcAttributeEntity.setActivityId(taskDefinition.getKey());//目标节点id
                LcReceiveParam lcReceiveParam = new LcReceiveParam();
                lcReceiveParam.setTaskId(taskId);
                lcReceiveParam.setActivityId(taskDefinition.getKey());
                boolean mutil = activitiUtil.validateNodeIsMultiInstance(lcReceiveParam);
                if(mutil){
                    lcAttributeEntity.setMutil(ActivitiUtil.ACT_CODE_20);//会签
                }else{
                    lcAttributeEntity.setMutil(ActivitiUtil.ACT_CODE_10);//非会签
                }
                lcAttributeEntities.add(lcAttributeEntity);//放入集合存储
            }
        }
    }

    /**
     * check状态
     * @param proInstId
     * @return
     */
    public ActivityProcessStatusEntity checkStatus(String proInstId){
        if(StringUtil.isEmpty(proInstId)){
            throw new ExceptionUtil("checkStatus未能获取到流程实例id");
        }
        List<Task> tasks = activitiUtil.getTaskService().createTaskQuery().processInstanceId(proInstId).list();
        String name = "";
        List<LcTask> lcTasks = new ArrayList<>();
        if(!CollectionUtil.isEmpty(tasks)){
            for(Task task: tasks){
                if(StringUtil.isEmpty(name)){
                    name = task.getName();
                }else{
                    name = name+","+task.getName();
                }
                //设置任务对象属性
                LcTask lcTask = new LcTask();
                lcTask.setAssignee(task.getAssignee());
                lcTask.setTaskId(task.getId());
                lcTask.setCategory(task.getCategory());
                lcTask.setOwner(task.getOwner());
                lcTask.setCreateTime(task.getCreateTime());
                lcTask.setFormKey(task.getFormKey());
                lcTask.setDescription(task.getDescription());
                lcTask.setDueDate(task.getDueDate());
                lcTask.setExecutionId(task.getExecutionId());
                lcTask.setName(task.getName());
                lcTask.setParentTaskId(task.getParentTaskId());
                lcTask.setProcessDefinitionId(task.getProcessDefinitionId());
                lcTask.setProcessInstanceId(task.getProcessInstanceId());
                lcTask.setProcessVariables(task.getProcessVariables());
                lcTask.setPriority(task.getPriority());
                lcTask.setTaskDefinitionKey(task.getTaskDefinitionKey());
                lcTask.setTenantId(task.getTenantId());
                lcTask.setSuspended(task.isSuspended());
                lcTasks.add(lcTask);
            }
        }
        Boolean isEnd = activitiUtil.validatePEnd(proInstId);
        ActivityProcessStatusEntity activityProcessStatusEntity = new ActivityProcessStatusEntity(proInstId,isEnd,name,lcTasks);
        return activityProcessStatusEntity;
    }

    /**
     * 验证是否为结束节点
     * @param bpmn
     * @param activityId
     */
    private boolean validateEnd(String bpmn,String activityId){
        if(StringUtil.isEmpty(bpmn)){
            throw new ExceptionUtil("验证结束节点时，bpmn为空！");
        }
        Boolean res  = activitiUtil.validateEnd(bpmn,activityId);
        return res;
    }

    /**
     * 查询指定节点已审批的人
     * @param lcReceiveNParam
     * @return
     */
    public BaseResult getNodeUser(LcReceiveNParam lcReceiveNParam){
        return activitiUtil.getNodeUser(lcReceiveNParam);
    }

    /**
     * 查询节点的未处理人及已处理人
     * @param lcReceiveNParam
     * @return
     */
    public BaseResult getNodeApproveUsers(LcReceiveNParam lcReceiveNParam){
        //1.获取未审批的人
        List<Task> taskList = activitiUtil.getNodeApproved(lcReceiveNParam);
        List<LcTaskApprovedEntity> lcTaskApprovedEntities = new ArrayList<>();
        if(!CollectionUtil.isEmpty(taskList)){
            for(Task task: taskList){
                lcTaskApprovedEntities.add(new LcTaskApprovedEntity(task.getAssignee(),null,null,false));
            }
        }
        //2.获取节点已审批人的人
        if(!StringUtil.isEmpty(lcReceiveNParam.getActivityId()) && !StringUtil.isEmpty(lcReceiveNParam.getProcessInstanceId())){
            LcApprovalParam lcApprovalParam = new LcApprovalParam();
            lcApprovalParam.setActivityId(lcReceiveNParam.getActivityId());
            lcApprovalParam.setInstanceId(lcReceiveNParam.getProcessInstanceId());
            List<LcApproval> lcApprovals = lcApprovalService.getLcApprovalList(lcApprovalParam);
            if(!CollectionUtil.isEmpty(lcApprovals)){
                for(LcApproval lcApproval: lcApprovals){
                    if(StringUtil.isEmpty(lcApproval.getBehaviorText())) {
                        String behavior = lcApproval.getBehavior();
                        switch (behavior) {
                            case ActivitiUtil.BEHAVIOR_0://提交
                                lcApproval.setBehaviorText("提交");
                                break;
                            case ActivitiUtil.BEHAVIOR_10://同意
                                lcApproval.setBehaviorText("同意");
                                break;
                            case ActivitiUtil.BEHAVIOR_20://驳回
                                lcApproval.setBehaviorText("驳回");
                                break;
                            case ActivitiUtil.BEHAVIOR_30://弃权
                                lcApproval.setBehaviorText("弃权");
                                break;
                            case ActivitiUtil.BEHAVIOR_40://撤回
                                lcApproval.setBehaviorText("撤回");
                                break;
                            case ActivitiUtil.BEHAVIOR_50://强行终止（终止流程）
                                lcApproval.setBehaviorText("终止流程");
                                break;
                            case ActivitiUtil.BEHAVIOR_60://执行跳转
                                lcApproval.setBehaviorText("跳转");
                                break;
                            case ActivitiUtil.BEHAVIOR_70://转办
                                lcApproval.setBehaviorText("转办");
                                break;
                            case ActivitiUtil.BEHAVIOR_80://委派
                                lcApproval.setBehaviorText("委派");
                                break;
                            case ActivitiUtil.BEHAVIOR_90://加签
                                lcApproval.setBehaviorText("加签");
                                break;
                            case ActivitiUtil.BEHAVIOR_100://催办
                                lcApproval.setBehaviorText("催办");
                                break;
                            case ActivitiUtil.BEHAVIOR_110://设置任务归属人
                                lcApproval.setBehaviorText("设置任务归属人");
                                break;
                            case ActivitiUtil.BEHAVIOR_120://挂起
                                lcApproval.setBehaviorText("挂起");
                                break;
                            case ActivitiUtil.BEHAVIOR_130://激活
                                lcApproval.setBehaviorText("激活");
                                break;
                            default:
                                lcApproval.setBehaviorText("缺省");
                        }
                    }
                    lcTaskApprovedEntities.add(new LcTaskApprovedEntity(lcApproval.getUserId(),lcApproval.getBehavior(),lcApproval.getBehaviorText(),true));
                }
            }
        }
        return BaseResult.success(lcTaskApprovedEntities);
    }

    /**
     *
     * @param list
     * @param historicTaskInstance
     * @param activityImpl
     */
    private void validateCanBatchLcHisMutil(List<String> list,HistoricTaskInstance historicTaskInstance,ActivityImpl activityImpl){
        try {
            addBatchLcHisMutil(list,historicTaskInstance.getProcessInstanceId(),activityImpl);//创建会签节点人员
        }catch (Exception e){
            log.error("创建会签节点人员失败：{}",e);
            throw new ExceptionUtil("创建会签节点人员失败,{}",e);
        }
    }


    /**
     * 流程干预（任意节点跳转）
     * @param lcReceiveNParam
     * @return
     */
    public BaseResult globalTask(LcReceiveNParam lcReceiveNParam){
        lcReceiveNParam.setBehavior(ActivitiUtil.BEHAVIOR_60);
        lcReceiveNParam.setEndAllActivityInstances(true);//需结束该运行实例下所有任务
//        if(StringUtil.isEmpty(lcReceiveNParam.getTaskId())){
//            throw new ExceptionUtil("未能获取到任务id");
//        }

        if(StringUtil.isEmpty(lcReceiveNParam.getProcessInstanceId())){
            throw new ExceptionUtil("未能获取到流程实例id");
        }
        if(StringUtil.isEmpty(lcReceiveNParam.getActivityId())){
            if(CollectionUtil.isEmpty(lcReceiveNParam.getLcReceiveParams())){
                throw new ExceptionUtil("目标参数不存在");
            }
            lcReceiveNParam.setActivityId(lcReceiveNParam.getLcReceiveParams().get(0).getActivityId());//目标节点
        }
        if(activitiUtil.validatePEnd(lcReceiveNParam.getProcessInstanceId())){
            throw new ExceptionUtil("流程实例已结束！");
        }
        boolean res = true;
        HistoricTaskInstance historicTaskInstance = null;
        Map<String,Object> map = new HashMap<>();
        List<LcReceiveParam> lcReceiveParamList = lcReceiveNParam.getLcReceiveParams();
        String deploymentId = "";
        if(!StringUtil.isEmpty(lcReceiveNParam.getTaskId())){
            deploymentId = activitiUtil.getDeploymentIdByTaskId(lcReceiveNParam.getTaskId());//根据当前任务id查找部署编号
            historicTaskInstance = activitiUtil.getTaskById(lcReceiveNParam.getTaskId());//根据当前任务id查找流程实例
        }else if(!StringUtil.isEmpty(lcReceiveNParam.getProcessInstanceId())){
            deploymentId = activitiUtil.getDeploymentIdByProcInstId(lcReceiveNParam.getProcessInstanceId());
            List<HistoricTaskInstance> historicTaskInstances = activitiUtil.getHistoryService()
                    .createHistoricTaskInstanceQuery().unfinished().orderByTaskId().desc()// 创建历史任务实例查询
                    .processInstanceId(lcReceiveNParam.getProcessInstanceId()) // 用流程实例id查询
//				.finished() // 查询已经完成的任务
                    .list();
            if(CollectionUtil.isNotEmpty(historicTaskInstances)){
                historicTaskInstance = historicTaskInstances.get(0);
                lcReceiveNParam.setTaskId(historicTaskInstance.getId());
            }else{
                throw new ExceptionUtil("当前流程实例已完成");
            }
        }

        String currentActivityId = null;
        String currentName = null;
        if(null != historicTaskInstance){
            currentActivityId = historicTaskInstance.getTaskDefinitionKey();//当前审批节点id
            currentName = historicTaskInstance.getName();//当前审批任务节点名称
        }
        String targetActivityId = lcReceiveNParam.getLcReceiveParams().get(0).getActivityId();
        if(StringUtil.isEmpty(targetActivityId)){
            throw new ExceptionUtil("未能获取到目标节点");
        }

        if(!CollectionUtil.isEmpty(lcReceiveParamList)){
            for(LcReceiveParam lcReceiveParam :lcReceiveParamList){
                lcReceiveParam.setNeedHandledTransactor(true);
                if(!StringUtil.isEmpty(deploymentId) && null != historicTaskInstance){
                    LcDeploymentHis lcDeploymentHis = lcDeploymentHisService.getLcDeploymentHisByDeploymentId(deploymentId);
                    if(null != lcDeploymentHis){

                        //获取目标节点
                        LcReceiveParam param = new LcReceiveParam();
                        param.setProcessInstanceId(historicTaskInstance.getProcessInstanceId());
                        if(!StringUtil.isEmpty(lcReceiveParam.getActivityId())){
                            param.setActivityId(lcReceiveParam.getActivityId());
                        }else{
                            param.setActivityId(targetActivityId);
                            lcReceiveParam.setActivityId(targetActivityId);//设定目标节点
                        }
                        boolean mutil = activitiUtil.validateNodeIsMultiInstance(param);

                        //如果是会签节点并且会签集合不存在则抛异常
                        if(mutil){
                            throw new ExceptionUtil("目标节点为会签节点不能设置");
                        }
                    }
                }
            }
        }
        lcReceiveNParam.setVariables(map);//设置变量
        lcReceiveNParam.setActivityId(targetActivityId);
        activitiUtil.jump(lcReceiveNParam);//注意此时跳转后 不需要终止 还是要继续执行下面命令为了重新分配人等等

        log.info("执行完成任务动作,分配节点执行人");
        setAssignee(historicTaskInstance,lcReceiveNParam);//设置处理人

        //返回流程实例是否结束
        ActivityProcessStatusEntity activityProcessStatusEntity = checkStatus(historicTaskInstance.getProcessInstanceId());
        activityProcessStatusEntity.setCurrentActivityId(currentActivityId);
        activityProcessStatusEntity.setCurrentName(currentName);
        BaseResult baseResult = new BaseResult();
        baseResult.setData(activityProcessStatusEntity);
        baseResult.setSuccess(res);
        return baseResult;
    }

    /**
     * 流程干预（转办）
     * @param lcReceiveNParam
     * @return
     */
    public BaseResult globalTransfer(LcReceiveNParam lcReceiveNParam){
        lcReceiveNParam.setBehavior(ActivitiUtil.BEHAVIOR_70);
        if(StringUtil.isEmpty(lcReceiveNParam.getTaskId())){
            throw new ExceptionUtil("未能获取到任务id");
        }

        if(lcReceiveNParam.isSetOwner()){//如果需要指定任务所属人 则进行设置 将来可以找到
            activitiUtil.setOwner(lcReceiveNParam.getTaskId(),lcReceiveNParam.getOwnerId());
        }
        HistoricTaskInstance historicTaskInstance = activitiUtil.getTaskById(lcReceiveNParam.getTaskId());
        if(null ==historicTaskInstance){
            throw new ExceptionUtil("转办任务时，任务不存在");
        }
//        persistenceAppro(historicTaskInstance,lcReceiveNParam);//持久化日志
        String mutilValue = lcReceiveNParam.getMutilValue();
        if(StringUtil.isEmpty(mutilValue)){
            throw new ExceptionUtil("转办人不存在");
        }
        lcReceiveNParam.setMutilValue(mutilValue);
        boolean b = activitiUtil.setAssignee(lcReceiveNParam.getTaskId(), mutilValue);
        BaseResult baseResult = new BaseResult();
        if(!b){
            throw new ExceptionUtil("转办失败");
        }
        String currentActivityId =historicTaskInstance.getTaskDefinitionKey();
        String currentName = historicTaskInstance.getName();//当前审批任务节点名称
        ActivityProcessStatusEntity activityProcessStatusEntity = checkStatus(historicTaskInstance.getProcessInstanceId());
        activityProcessStatusEntity.setCurrentActivityId(currentActivityId);
        activityProcessStatusEntity.setCurrentName(currentName);
        baseResult.setData(activityProcessStatusEntity);
        return baseResult;
    }

    /**
     * 流程干预（根据流程实例查找最新任务）
     * @param processInstanceId
     * @return
     */
    public BaseResult<List<LcTaskEntity>> getRunTaskByInstanceId(String processInstanceId){
        if(StringUtil.isEmpty(processInstanceId)){
            throw new ExceptionUtil("未能获取到流程实例id");
        }
        List<LcTaskEntity> lcTaskEntities =  new ArrayList<>();
        List<Task> tasks = activitiUtil.getTaskListByProcessInstanceId(processInstanceId);
        if(CollectionUtil.isNotEmpty(tasks)){
            for(Task task:tasks){
                LcTaskEntity lcTaskEntity = new LcTaskEntity();
                lcTaskEntity.setTaskId(task.getId());
                lcTaskEntity.setUserId(task.getAssignee());
//                lcTaskEntity.setOwnerId(task.getOwner());
                lcTaskEntities.add(lcTaskEntity);
            }
        }

        return BaseResult.success(lcTaskEntities);
    }

    /**
     * 全局强制处理任意节点跳转（包括流程实例已结束，正在运行实例均支持）
     * @param lcReceiveNParam
     * @return
     */
    public BaseResult globalForceJumpTask(LcReceiveNParam lcReceiveNParam){
        return BaseResult.success();
    }

    /**
     * 撤回（流程实例已结束，正在运行强制撤回方式）
     * @param lcReceiveNParam
     * @return
     */
    public BaseResult globalForceCallBack(LcReceiveNParam lcReceiveNParam){
        boolean res = true;

        LcNodeAttribute lcNodeAttribute = getLcNodeAttributeByTaskId(lcReceiveNParam.getTaskId());//当前节点扩展属性

        if(null != lcNodeAttribute && !StringUtil.isEmpty(lcNodeAttribute.getRecall()) && ActivitiUtil.ACT_CODE_10.equals(lcNodeAttribute.getRecall())){
            log.warn("撤回操作时，该节点配置了不允许主动撤回操作！{}",lcReceiveNParam);
            throw new ExceptionUtil("撤回操作时，该节点配置了不允许主动撤回操作！");
        }

        lcReceiveNParam.setBehavior(ActivitiUtil.BEHAVIOR_40);
        HistoricTaskInstance historicTaskInstance = activitiUtil.getTaskById(lcReceiveNParam.getTaskId());//从历史中找到自己提交的任务

        //不能被撤回到会签节点
        String procDefId = historicTaskInstance.getProcessDefinitionId();
        if(StringUtil.isEmpty(procDefId)){
            log.warn("撤回操作时，未能查到流程定义id！{}",lcReceiveNParam);
            throw new ExceptionUtil("撤回操作时，未能查到流程定义id！");
        }
        ProcessDefinition processDefinition = activitiUtil.getProcessDefinitionByDid(procDefId);
        if(null == processDefinition){
            log.warn("撤回操作时，未能查到流程定义！{}-{}",lcReceiveNParam,processDefinition);
            throw new ExceptionUtil("撤回操作时，未能查到流程定义id！");
        }
        String deploymentId = processDefinition.getDeploymentId();
        if(StringUtil.isEmpty(procDefId)){
            log.warn("撤回操作时，未能查到流程部署id！{}",lcReceiveNParam);
            throw new ExceptionUtil("撤回操作时，未能查到流程部署id！");
        }
        LcDeploymentHis lcDeploymentHis = lcDeploymentHisService.getLcDeploymentHisByDeploymentId(deploymentId);
        if(null == lcDeploymentHis){
            log.warn("撤回操作时，未能查到流程部署对象！{}",lcReceiveNParam);
            throw new ExceptionUtil("撤回操作时，未能查到流程部署对象！");
        }

        String bpmn = lcDeploymentHis.getBpmn();
        UserTask userTask = activitiUtil.getUserTask(bpmn,historicTaskInstance.getTaskDefinitionKey());

        if(null == userTask){
            log.warn("撤回操作时，未能查到UserTask！{}",lcReceiveNParam);
            throw new ExceptionUtil("撤回操作时，未能查到UserTask！");
        }
        boolean mutil = activitiUtil.validateNodeIsMultiInstance(userTask);
        if(mutil){
            //撤回到的节点是会签节点不能撤回
            log.warn("撤回操作时，该节点为会签节点不能撤回！{}",lcReceiveNParam);
            throw new ExceptionUtil("该节点为会签节点不能撤回！");
        }

        if(activitiUtil.validatePEnd(historicTaskInstance.getProcessInstanceId())){
            //流程结束则采用sql方式重新创建
            return createTask(historicTaskInstance,lcReceiveNParam);
        }

        validateAllowRecall(historicTaskInstance);//验证当前运行的任务节点是否可被撤回

        //取出历史任务对应的节点（bpm文件中节点编号）
        lcReceiveNParam.setActivityId(historicTaskInstance.getTaskDefinitionKey());//即表示即将要退回到该节点

        //取出当前流程下的活动任务
        List<Task> tasks = activitiUtil.getTaskListByProcessInstanceId(historicTaskInstance.getProcessInstanceId());
        if(!CollectionUtil.isEmpty(tasks)){
            lcReceiveNParam.setTaskId(tasks.get(0).getId());//设置为任务 表示通过这个任务跳转到指定节点
        }

        activitiUtil.jump(lcReceiveNParam);//执行跳转至指定节点

        setAssignee(historicTaskInstance,lcReceiveNParam);//设置处理人

        persistenceAppro(historicTaskInstance,lcReceiveNParam);//持久化日志

        //返回流程实例是否结束
        ActivityProcessStatusEntity activityProcessStatusEntity = new ActivityProcessStatusEntity(historicTaskInstance.getProcessInstanceId(),activitiUtil.validatePEnd(historicTaskInstance.getProcessInstanceId()));
        BaseResult baseResult = new BaseResult();
        baseResult.setData(activityProcessStatusEntity);
        baseResult.setSuccess(res);
        return baseResult;
    }

    /**
     * 创建任务
     * @param historicTaskInstance
     * @param lcReceiveNParam
     */
    private BaseResult createTask(HistoricTaskInstance historicTaskInstance,LcReceiveNParam lcReceiveNParam){
        boolean res = true;
        try{
            HistoricProcessInstance historicProcessInstance = activitiUtil.getHistoryProcessInstance(historicTaskInstance.getProcessInstanceId());
            //1创建Execution
            ActRuExecution actRuExecution =  new ActRuExecution();
            actRuExecution.setRev(1);
            actRuExecution.setProcDefId(historicTaskInstance.getProcessDefinitionId());//流程定义id
            actRuExecution.setProcInstId(historicTaskInstance.getProcessInstanceId());//流程实例id
            actRuExecution.setActId(historicTaskInstance.getTaskDefinitionKey());//节点id
            actRuExecution.setId(historicTaskInstance.getExecutionId());//流程运行实例id
//            actRuExecution.setParentId(historicTaskInstance.getProcessInstanceId());//上级id
            //子execution分支的is_scope的值为0，主分支的为1。这里一定要设置，否则只能暂时退回，再走一个节点该execution就会被删除
            actRuExecution.setIsScope(1);
            actRuExecution.setIsActive(0);
            actRuExecution.setIsEventScope(0);
            actRuExecution.setIsConcurrent(0);
            actRuExecution.setCachedEntState(2);
            actRuExecution.setSuspensionState(1);
            if(null != historicProcessInstance){
                actRuExecution.setBusinessKey(historicProcessInstance.getBusinessKey());
            }
            actRuExecutionDao.addActRunExecution(actRuExecution);

            //2.创建Task
            ActRuTask actRuTask = new ActRuTask();
            actRuTask.setRev(1);
            actRuTask.setId(historicTaskInstance.getId());
            actRuTask.setName(historicTaskInstance.getName());
            actRuTask.setParentTaskId(historicTaskInstance.getParentTaskId());
            actRuTask.setDescription(historicTaskInstance.getDescription());
            actRuTask.setPriority(historicTaskInstance.getPriority());
            actRuTask.setCreateTime(historicTaskInstance.getCreateTime());
            actRuTask.setOwner(historicTaskInstance.getOwner());
            actRuTask.setAssignee(historicTaskInstance.getAssignee());
            actRuTask.setExecutionId(historicTaskInstance.getExecutionId());
            actRuTask.setProcInstId(historicTaskInstance.getProcessInstanceId());
            actRuTask.setProcDefId(historicTaskInstance.getProcessDefinitionId());
            actRuTask.setTaskDefKey(historicTaskInstance.getTaskDefinitionKey());
            actRuTask.setDueDate(historicTaskInstance.getDueDate());
            actRuTask.setSuspensionState(1);//激活
            actRuTask.setTenantId(historicTaskInstance.getTenantId());
            actRuTask.setFormKey(historicTaskInstance.getFormKey());
            actRuTask.setCategory(historicTaskInstance.getCategory());
            actRuTaskDao.addActRuTask(actRuTask);

            //3.创建运行时人员
            Map<String,Object> condition = new HashMap<>();
            condition.put("procInstId",historicTaskInstance.getProcessInstanceId());
            condition.put("taskId",historicTaskInstance.getId());
            List<ActRuIdentitylink> actRuIdentitylinkList = actHiIdentitylinkDao
                    .getActHiIdentitylinkList(condition);
            if(CollectionUtil.isNotEmpty(actRuIdentitylinkList)){
                for(ActRuIdentitylink actRuIdentitylink : actRuIdentitylinkList){
                    actRuIdentitylinkDao.addActRuIdentitylink(actRuIdentitylink);
                }
            }

            //4.创建运行时变量
            List<HistoricVariableInstance> historicVariableInstances = activitiUtil.getHistoryService().createHistoricVariableInstanceQuery()
                    .executionId(historicTaskInstance.getExecutionId()).list();
            if(CollectionUtil.isNotEmpty(historicVariableInstances)){
                for(HistoricVariableInstance historicVariableInstance : historicVariableInstances){
                    ActRuVariable actRuVariable = new ActRuVariable();
                    actRuVariable.setId(historicVariableInstance.getId());
                    actRuVariable.setName(historicVariableInstance.getVariableName());
                    actRuVariable.setType(historicVariableInstance.getVariableTypeName());
                    actRuVariable.setText(""+historicVariableInstance.getValue());
                    actRuVariable.setExecutionId(historicVariableInstance.getProcessInstanceId());
                    actRuVariable.setProcInstId(historicVariableInstance.getProcessInstanceId());
                    actRuVariable.setTaskId(historicVariableInstance.getTaskId());
                    actRuVariable.setRev(1);
                    actRunVariableDao.addActRunVariable(actRuVariable);
                }
            }

            //5.更新该任务为未完成
            Map<String,Object> map = new HashMap<>();
            map.put("endTime",null);
            map.put("id",historicTaskInstance.getId());
            actHiTaskinstDao.updateActHiTaskInstEndTime(map);
            persistenceAppro(historicTaskInstance,lcReceiveNParam);//持久化日志
        }catch (Exception e){
            log.error("手动追回流程至指定节点异常{}",e);
            throw new ExceptionUtil("手动追回流程至指定节点异常！");
        }

        //返回流程实例是否结束
        ActivityProcessStatusEntity activityProcessStatusEntity = new ActivityProcessStatusEntity(historicTaskInstance.getProcessInstanceId(),activitiUtil.validatePEnd(historicTaskInstance.getProcessInstanceId()));
        BaseResult baseResult = new BaseResult();
        baseResult.setData(activityProcessStatusEntity);
        baseResult.setSuccess(res);
        return baseResult;
    }


    /**
     * 验证当前运行的任务节点是否可被撤回
     * @param historicTaskInstance
     */
    private void validateAllowRecall(HistoricTaskInstance historicTaskInstance){
        List<Task> tasks = activitiUtil.findTaskListByInstanceId(historicTaskInstance.getProcessInstanceId());
        if(CollectionUtil.isNotEmpty(tasks)){
            for(Task task:tasks){
                LcNodeAttribute lcNodeAttribute = getLcNodeAttributeByTaskId(task.getId());
                if(null != lcNodeAttribute && !StringUtil.isEmpty(lcNodeAttribute.getAllowRecall()) && ActivitiUtil.ACT_CODE_10.equals(lcNodeAttribute.getAllowRecall())){
                    log.warn("撤回操作时，当前运行的任务所对应的节点配置了不允许被撤回！{}",lcNodeAttribute);
                    throw new ExceptionUtil("撤回操作时，当前运行的任务所对应的节点配置了不允许被撤回！");
                }
            }
        }
    }

    /**
     * 获取目标节点并设置LcReceiveNParam中目标节点
     * @param lcNodeAttribute
     * @param lcReceiveNParam
     * @return
     */
    private String setLcReceiveNParam(LcNodeAttribute lcNodeAttribute,LcReceiveNParam lcReceiveNParam){
        String targetActivityId = "";
        //如果节点配置中目标节点为多个 则抛出异常 原因无法确定选择哪个节点
        //如果节点配置中目标节点只有一个节点 优先级调出
        //如果节点配置中目标节点没有节点 则通过设计器中连线拿出目标节点
        //如果节点配置中目标节点没有节点 并且设计器中连线不存在目标节点则抛出异常
        if(null == lcNodeAttribute){
            List<TaskDefinition> taskDefinitions = activitiUtil.getNextTaskDefinitionList(lcReceiveNParam.getTaskId(),lcReceiveNParam.getVariables());
            if(CollectionUtil.isEmpty(taskDefinitions)){
                throw new ExceptionUtil("当前节点的未配置目标节点并且流程设计器中也没有连线目标节点！");
            }
            if(taskDefinitions.size()>1){
                throw new ExceptionUtil("当前节点的未配置目标节点并且流程设计器中目标节点有多个连线！");
            }
            targetActivityId = taskDefinitions.get(0).getKey();
        }else{
            List<LcNodeBtn> nodeBtns = lcNodeAttribute.getLcNodeBtns();
            if(CollectionUtil.isNotEmpty(nodeBtns)){
                List<LcNodeBtn> behaviorLcNodeBtnList = new ArrayList<>();
                for(LcNodeBtn nodeBtn: nodeBtns){
                    LcBtn lcBtn = nodeBtn.getLcBtn();
                    if(lcBtn.getBehavior().equals(lcReceiveNParam.getBehavior())){
                        behaviorLcNodeBtnList.add(nodeBtn);
                    }
                }
                if(CollectionUtil.isNotEmpty(behaviorLcNodeBtnList)){
                    if(behaviorLcNodeBtnList.size()>1){
                        log.info("当前任务对应的节点，在节点配置中，相同按钮存在多个！",lcNodeAttribute);
                        throw new ExceptionUtil("当前任务对应的节点，在节点配置中，相同按钮存在多个！");
                    }
                    List<LcJumpRules> lcJumpRules = behaviorLcNodeBtnList.get(0).getLcJumpRules();
                    if(CollectionUtil.isNotEmpty(lcJumpRules)){
                        if(lcJumpRules.size()>1){
                            log.info("当前任务对应的节点，在节点配置中，目标节点存在多个！",lcNodeAttribute);
                            throw new ExceptionUtil("当前任务对应的节点，在节点配置中，目标节点存在多个！");
                        }
                        targetActivityId = lcJumpRules.get(0).getTargetNodeId();
                    }
                }
            }
        }
        lcReceiveNParam.setActivityId(targetActivityId);
        return targetActivityId;
    }
}